Run-length encoding — compress repeated characters
"aaabbc" -> "a3b2c1". Decoding walks the encoded string reading a letter followed by its digit-run count. Demonstrates per-char scanning, run counting, and reconstructing a string by repetition. Run: soma run run_length.cell --signal encode "aaabbbcccd"
A Soma program from the text part of the verified corpus: 66 lines, cells RunLength, RunLengthTest. It passes soma check with soma 3.2.4.
How it is built
The cell RunLength declares 2 signals in its face: encode(s: String) -> String and decode(s: String) -> String. Handlers: encode (line 17) and decode (line 35).
The file also holds 1 test cell (RunLengthTest) with 5 assertions, run by soma test.
The source
run_length.cell
// ============================================================================
// Run-length encoding — compress repeated characters
// ============================================================================
//
// "aaabbc" -> "a3b2c1". Decoding walks the encoded string reading a letter
// followed by its digit-run count. Demonstrates per-char scanning, run
// counting, and reconstructing a string by repetition.
//
// Run: soma run run_length.cell --signal encode "aaabbbcccd"
cell RunLength {
face {
signal encode(s: String) -> String
signal decode(s: String) -> String
}
on encode(s: String) {
if len(s) == 0 { return "" }
let out = ""
let prev = s[0]
let count = 1
for i in range(1, len(s)) {
let c = s[i]
if c == prev {
count = count + 1
} else {
out = out + prev + to_string(count)
prev = c
count = 1
}
}
return out + prev + to_string(count)
}
on decode(s: String) {
let out = ""
let i = 0
let n = len(s)
while i < n {
let ch = s[i]
i = i + 1
// read the digit run that follows
let num = ""
while i < n && s[i] >= "0" && s[i] <= "9" {
num = num + s[i]
i = i + 1
}
let reps = to_int(num)
for j in range(0, reps) {
out = out + ch
}
}
return out
}
}
cell test RunLengthTest {
rules {
assert encode("aaabbbcccd") == "a3b3c3d1"
assert encode("") == ""
assert encode("x") == "x1"
assert decode("a3b3c3d1") == "aaabbbcccd"
assert decode(encode("wwwwwwwwwwaa")) == "wwwwwwwwwwaa"
}
}What the toolchain says
$ soma check run_length.cell
warning: `num` grows by concatenation inside a loop — each step copies the whole value, so the loop is quadratic (8 MB took 32 s, a list + join() 30 ms): push the pieces to a List and `join(parts, "")` once
--> run_length.cell:45:17
|
45 | num = num + s[i]
| ^
✓ 1 warning(s), no errors.$ soma test run_length.cell
test RunLengthTest ...
✓ assert encode("aaabbbcccd") == "a3b3c3d1"
✓ assert encode("") == ""
✓ assert encode("x") == "x1"
✓ assert decode("a3b3c3d1") == "aaabbbcccd"
✓ assert decode(encode("wwwwwwwwwwaa")) == "wwwwwwwwwwaa"
5 tests: 5 passed, 0 failed$ soma verify run_length.cell
Verifying run_length.cell...
RunLength/termination:
⚠ handler `decode`: while-loop without provable termination bound (write `while [loop_bound(N)] cond { … }`, or a for-loop over a bounded range)
0 passed, 1 warnings, 0 failures
Temporal: 0 passed, 0 failed
VERIFY OK