Date: 2026-06-06
Time: 16:17
design-compressed-string-iterator/solution.pyThis file implements LeetCode 604 — Design Compressed String Iterator. It provides a StringIterator class that lazily decompresses a run-length encoded string one character at a time, without ever materializing the full expanded string. The file also contains its own test suite inline.
StringIterator — The core class. Constructed with a compressed string like "L1e2t1C1o1d1e1" where each letter is followed by its repetition count (which can be multi-digit).
_init(self, compressedString) — Stores the raw string and initializes a cursor (i), then immediately calls extractnext() to prime the first character/count pair.extractnext(self) — Parses the next (char, count) pair from s starting at position i. Reads one character, then scans forward through consecutive digits to build the count. If the string is exhausted, sets char = ' ' and count = 0 as sentinel values.next(self) -> str — Returns the current character and decrements the count. When the count hits zero, advances to the next pair. Returns ' ' (space) if exhausted.hasNext(self) -> bool — Returns True iff _count > 0.Lazy cursor-based parsing. Rather than pre-parsing all (char, count) pairs into a list, the iterator maintains a read cursor (i) and only parses the next pair when the current one is fully consumed. This gives O(1) memory regardless of how large the counts are — important since counts can reach 10^9 (see testlarge_count).
Sentinel-based exhaustion. When the input is consumed, the iterator falls into a terminal state where char = ' ' and count = 0. The space character doubles as both the sentinel and the return value for next() after exhaustion — this matches the LeetCode spec exactly.
Self-contained test module. Tests live in the same file via unittest.TestCase and run with python -m unittest or python solution.py. A separate test_solution.py exists alongside it for the project's test harness.
Imports: Only unittest from the standard library. No external dependencies.
Imported by: The massive Imported By list in the repo context is misleading — those are cross-references from a code-expert indexing tool, not actual Python imports. The real consumer is design-compressed-string-iterator/test_solution.py, which imports StringIterator from this module.
1. Constructor receives "a12b3", stores it, sets cursor _i = 0.
2. extractnext() reads s[0] → 'a', scans digits s[1:3] → "12", sets char = 'a', count = 12, advances _i = 3.
3. Each next() call returns 'a' and decrements count. On the 12th call, count hits 0 and extractnext() fires again: reads 'b', count 3, _i = 5.
4. After 3 more next() calls, extractnext() finds i >= len(s), sets the sentinel state.
5. Subsequent next() calls return ' ' indefinitely.
count >= 0 always. count is decremented only when hasNext() is true (i.e., _count > 0), so it never goes negative.extractnext is called exactly once per pair. It fires in the constructor and then only when _count reaches zero inside next(). It's never called from hasNext().hasNext() is pure. It has no side effects — calling it repeatedly doesn't advance the iterator. The test testhasnextdoesnot_consume verifies this."12a" would produce undefined behavior.There is none. The code trusts its input per the LeetCode contract. If s contains no digits after a character, int(self.s[self._i:j]) would receive an empty string and raise ValueError. This is by design — the problem guarantees valid input.