Arbitrary strings, including empty strings and delimiter characters, must be concatenated and later recovered without escaping ambiguity.
Keep true
At the start of each decode loop, index points to the first decimal length digit. After locating # and consuming exactly length payload characters, index points to the next length or end of data.
Reuse it
Prefix variable-length records with a parseable size so payload bytes remain opaque; this framing pattern transfers to network protocols, file formats, and binary serialization.
Read it this way: The first input string has length 4, so encoding emits 4#lint. Step through the frames to watch the state change. The last frame shows the answer or the stopping condition.
Pattern: Length prefix.
Simple idea: Save each string as length#text. The decoder reads the length first, so
the text may contain any character, including #.
def encode_strings(strings: list[str]) -> str: return "".join(f"{len(text)}#{text}" for text in strings)def decode_strings(data: str) -> list[str]: strings = [] index = 0 while index < len(data): separator = data.index("#", index) length = int(data[index:separator]) index = separator + 1 strings.append(data[index : index + length]) index += length return strings