find substring with count and return even frequency substring list
Your code is really hard to understand. When I read the description I noticed three steps:


Extract ID and message count.
Total duplicate message counts.
Return a round robin of these IDs.


You've got 1&amp;2 mangled together, and 3 nicely by itself.

Since you're using Python, it's easier to read iterator based approaches to these things. Firstly you can replace your step 3 with a recipe from the itertools standard library. All you need to do is call itertools.repeat beforehand.

It's not immediately clear what your code is doing when you've mangled indexed iteration with business logic, with step 2 as well. And so I suggest re-writing it. You know the data will come in the form {type}{message}{amount}, where the type and amount has a length of 1, and message is either 2 or 3. And so to extract the messages and amounts you can just use next/islice on an iterator. Using a try while loop. After this totaling the message counts is simple.

Also if you're going to use typing you should use mypy too, and put type information on both the arguments and return types.

from typing import List, Iterator, Tuple, Sequence, TypeVar
    import itertools

MESSAGE_LENGTH = {
    'I': 3,
    'A': 2
}

TValue = TypeVar('TValue')


def roundrobin(*iterables: Tuple[Sequence[TValue], ...]) -&gt; Iterator[TValue]:
    "roundrobin('ABC', 'D', 'EF') --&gt; A D E B F C"
    # Recipe credited to George Sakkis
    num_active = len(iterables)
    nexts = itertools.cycle(iter(it).__next__ for it in iterables)
    while num_active:
        try:
            for next in nexts:
                yield next()
        except StopIteration:
            # Remove the iterator we just exhausted from the cycle.
            num_active -= 1
            nexts = itertools.cycle(itertools.islice(nexts, num_active))


def extract_messages(input: Iterator[str]) -&gt; Iterator[Tuple[str, int]]:
    input = iter(input)
    message_type = next(input)
    while True:
        length = MESSAGE_LENGTH[message_type]
        message = ''.join([message_type] + list(itertools.islice(input, length)))
        message_type = next(input)
        number = []
        try:
            while message_type not in MESSAGE_LENGTH:
                number += [message_type]
                message_type = next(input)
        except StopIteration:
            break
        finally:
            yield message, int(''.join(number))


def parse_message(string: str) -&gt; List[str]:
    message_counts = {}
    for message, amount in extract_messages(string):
        message_counts.setdefault(message, 0)
        message_counts[message] += amount

    return list(roundrobin(*(
        itertools.repeat(key, amount)
        for key, amount in message_counts.items()
    )))


if __name__ == '__main__':
    print(parse_message('Akb2IAld3'))
    print(parse_message('Aqp1Iasd2Aqp4IAbd1'))
    print(parse_message('Aqp1Iasd2Aqp4IAbd10'))