Run-length encoding replaces each consecutive run of equal values with that value and its count.
Python exercise: encode consecutive states without merging distant runs
Operation contract
The receipt-status stream contains two queued runs separated by a sent state. The encoder keeps those queued runs separate; a Counter would merge their totals and lose order. It rejects non-ASCII, nonalphabetic states and caps input length before scanning. The empty input has an empty encoding, which the decoder can distinguish from a missing field only if the caller declares that policy.
Failure and ownership boundary
This is a teaching encoder, not a compression format with framing, escaping or integrity checks. Long runs and attacker-controlled counts need limits in any decoder. Python Counter and deque: counts, queues and bounded history solves a different question; Python struct: a fixed-endian receipt record with exact byte length explains why wire compression needs more than this loop.
Working program
def encode_states(states):
if type(states) is not str or len(states) > 100 or not states.isascii() or not states.isalpha():
if states != "":
raise ValueError("ASCII status sequence")
if not states:
return []
encoded = []
current, count = states[0], 1
for state in states[1:]:
if state == current:
count += 1
else:
encoded.append((current, count))
current, count = state, 1
encoded.append((current, count))
return encoded
print(encode_states("QQSQQ"))
print(encode_states(""))
try:
encode_states("Q1")
except ValueError:
print("non-ASCII state rejected")Output
[('Q', 2), ('S', 1), ('Q', 2)]
[]
non-ASCII state rejectedCosts and limits
The scan costs O(n) time and O(r) output for r runs. A sequence with no repeated adjacent states can make the encoded representation larger than the input; compression is not guaranteed.
Common Mistakes
- A Counter loses run boundaries and order.
- A decoder must cap declared counts before allocating output.
Connected lessons
Python Counter and deque: counts, queues and bounded history, Python struct: a fixed-endian receipt record with exact byte length, Python strings and bytes: reject decoding errors before parsing records.
