"""
Created by Hadron DaVinci
https://hadrondavinci.com

For Educational Purposes
To Run:
    1) Download https://hadrondavinci.com/assets/code/2020-12-05/method1.py
    2) python method1.py

Expected Output:
I: 12
II: 123
ID: 132
IID: 1243
IIDD: 12543
IIDDD: 126543
D: 21
DD: 321
DI: 213
DDI: 3214
DDII: 32145
DDIDDIID: 321654798
"""


class Zoo:
    def __init__(self, _str):
        """
        :param _str: input string of I's and D's
        """
        self.input = _str
        self.digit_index = 1
        self.current_trend = None
        self.result = ''

    def get_trend_count(self, trend: str, index: int) -> int:
        """
        Counts the number of trend characters which are the same
        in this part of input.

        For example:
            with 'DDDDII',  at i=0 (the trend that starts at beginning of input string), there are 4 D's
            with 'IIDDIII', at i=0 (the trend that starts at beginning of input string), there are 2 I's

        :param trend: current string being counted. Can be either an 'I' or a 'D'
        :param index: location where the trend starts in input string
        """
        start_index = index
        while self.input[index] == trend:
            index += 1
            if index == len(self.input):
                break
        return index - start_index

    def get_trend_result(self, trend: str, trend_count: int):
        """
        Uses information about the trend, trend_count, and digit index to calculate
        the trend result.

        For example,
            with 4 D's and a digit index of 1, this produces: 4321
            with 4 D's and a digit index of 2, this produces: 5432
            with 4 D's and a digit index of 3, this produces: 6543

            with 4 I's and a digit index of 1, this produces: 1234
            with 4 I's and a digit index of 2, this produces: 2345
            with 4 I's and a digit index of 3, this produces: 3456

        :param trend: current string being counted. Can be either an 'I' or a 'D'
        :param trend_count: number of characters in trend
        """
        range_end = self.digit_index + trend_count + 1
        local_result = ''
        index = self.digit_index
        for index in range(index, range_end):
            if trend == 'I':
                local_result = local_result + str(index)
            elif trend == 'D':
                local_result = str(index) + local_result
        self.digit_index = index
        return local_result

    def modify_local_result(self, trend: str, trend_count: int, local_result: str, index: int) -> str:
        """
        Modifies local_result when trend is 'I' by removing digits it shares with adjacent 'D' trends

        When (index + trend_count) < len(_input), this 'I' trend finishes before end of string which implies
        there is a D trend to the right

        When index != 0. this 'I' trend is not the first trend which implies
        there is a D trend to the left

        :param trend: the current string being counted. Can be either an 'I' or a 'D'
        :param trend_count: number of characters in trend
        :param local_result: string being modified
        :param index: location where the trend starts in input string
        """
        if trend == 'D':                                # don't modify if trend is D
            return local_result

        if (index + trend_count) < len(self.input):     # when there is a D trend to the right, remove right digit
            local_result = local_result[:-1]

        if index != 0:                                  # when there is a D trend to the left, remove left digit
            local_result = local_result[1:]

        return local_result

    def main(self) -> int:
        """
        Runs main logic
        """
        i = 0
        while i < len(self.input):
            current_trend = self.input[i]
            trend_count = self.get_trend_count(current_trend, i)
            local_result = self.get_trend_result(current_trend, trend_count)
            local_result = self.modify_local_result(current_trend, trend_count, local_result, i)
            self.result += local_result
            i += trend_count

        return self.result


def foo(_input_str):
    f = Zoo(_input_str)
    result = f.main()
    print(f"{_input_str}:", result)
    return int(result)


if __name__ == "__main__":
    assert foo("I") == 12
    assert foo("II") == 123
    assert foo("ID") == 132
    assert foo("IID") == 1243
    assert foo("IIDD") == 12543
    assert foo("IIDDD") == 126543
    assert foo("D") == 21
    assert foo("DD") == 321
    assert foo("DI") == 213
    assert foo("DDI") == 3214
    assert foo("DDII") ==32145
    assert foo("DDIDDIID") == 321654798
