FA-75171 / CRDT convergence / Open access
Visible index translation: delete targets the character before the cursor index · case 01
Deleting index zero removes the last character; other deletes remove the preceding character.
ROOT CAUSE
The delete maps index i to visible element i-1, the insert anchor rule.
VERIFIED REPAIR
A delete at visible index i targets the visible element at i.
Unsuccessful approach: Clamping the shifted index fixes index zero but still deletes the preceding character elsewhere.
Case contract
A sequence CRDT holds [id, char, deleted]. Local edits use visible indices: ["insert", i, ch] (0 <= i <= visible length) references the visible element at i-1 (None at 0), is placed immediately after it, and gets id "L<k>" from a counter advanced only by accepted inserts; ["delete", i] (0 <= i < visible length) tombstones the visible element at i. Out-of-range edits yield ["reject", i]. Return the emitted ops and visible text.
Why this case matters
Editors translate cursor positions into identifier-based CRDT operations; tombstones make that translation error-prone.
1 / The failure
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(elements, edits):
seq = [list(e) for e in elements]
out = []
k = 0
for ed in edits:
vis = [i for i, e in enumerate(seq) if not e[2]]
idx = ed[1]
if ed[0] == 'insert':
if idx < 0 or idx > len(vis):
out.append(['reject', idx])
continue
if idx == 0:
after, pos = None, 0
else:
p = vis[idx - 1]
after, pos = seq[p][0], p + 1
k += 1
nid = 'L%d' % k
seq.insert(pos, [nid, ed[2], False])
out.append(['ins', nid, after])
else:
if idx < 0 or idx >= len(vis):
out.append(['reject', idx])
continue
p = vis[idx - 1]
seq[p][2] = True
out.append(['del', seq[p][0]])
return {'ops': out, 'text': ''.join(e[1] for e in seq if not e[2])}
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
cases = {
1: [('insert after tombstones uses the visible neighbour', [[['e0', 'a', False], ['e1', 'b', True], ['e2', 'c', True], ['e3', 'd', False], ['e4', 'e', False]], [['insert', 2, 'X']]], {'ops': [['ins', 'L1', 'e3']], 'text': 'adXe'}), ('insert at the visible end', [[['e0', 'a', False], ['e1', 'b', False], ['e2', 'c', True]], [['insert', 2, 'Z'], ['insert', 3, 'W']]], {'ops': [['ins', 'L1', 'e1'], ['ins', 'L2', 'L1']], 'text': 'abZW'}), ('insert at the start', [[['e0', 'a', True], ['e1', 'b', False], ['e2', 'c', False]], [['insert', 0, 'S']]], {'ops': [['ins', 'L1', None]], 'text': 'Sbc'}), ('delete by visible index', [[['e0', 'a', True], ['e1', 'b', False], ['e2', 'c', False], ['e3', 'd', True], ['e4', 'e', False], ['e5', 'f', False]], [['delete', 0], ['delete', 2]]], {'ops': [['del', 'e1'], ['del', 'e5']], 'text': 'ce'}), ('delete last visible character', [[['e0', 'a', False], ['e1', 'b', False], ['e2', 'c', False], ['e3', 'd', True]], [['delete', 2]]], {'ops': [['del', 'e2']], 'text': 'ab'}), ('out-of-range edits are rejected', [[['e0', 'a', False], ['e1', 'b', False]], [['insert', 4, 'q'], ['delete', 2], ['delete', -1], ['insert', -1, 'r'], ['insert', 1, 'k']]], {'ops': [['reject', 4], ['reject', 2], ['reject', -1], ['reject', -1], ['ins', 'L1', 'e0']], 'text': 'akb'}), ('ids stay dense after a rejection', [[['e0', 'x', False], ['e1', 'y', False]], [['insert', 5, 'p'], ['insert', 1, 'm'], ['insert', 0, 'n']]], {'ops': [['reject', 5], ['ins', 'L1', 'e0'], ['ins', 'L2', None]], 'text': 'nxmy'}), ('typing into an empty document', [[], [['insert', 0, 'h'], ['insert', 1, 'i'], ['insert', 2, '!']]], {'ops': [['ins', 'L1', None], ['ins', 'L2', 'L1'], ['ins', 'L3', 'L2']], 'text': 'hi!'}), ('mixed edits', [[['e0', 'h', False], ['e1', 'e', True], ['e2', 'l', False], ['e3', 'l', False], ['e4', 'o', False]], [['delete', 1], ['insert', 1, 'E'], ['insert', 4, '?']]], {'ops': [['del', 'e2'], ['ins', 'L1', 'e0'], ['ins', 'L2', 'e4']], 'text': 'hElo?'})],
2: [('insert after tombstones uses the visible neighbour', [[['e0', 'a', False], ['e1', 'b', True], ['e2', 'c', True], ['e3', 'd', False], ['e4', 'e', False]], [['insert', 2, 'X']]], {'ops': [['ins', 'L1', 'e3']], 'text': 'adXe'}), ('insert at the visible end', [[['e0', 'a', False], ['e1', 'b', False], ['e2', 'c', True]], [['insert', 2, 'Z'], ['insert', 3, 'W']]], {'ops': [['ins', 'L1', 'e1'], ['ins', 'L2', 'L1']], 'text': 'abZW'}), ('insert at the start', [[['e0', 'a', True], ['e1', 'b', False], ['e2', 'c', False]], [['insert', 0, 'S']]], {'ops': [['ins', 'L1', None]], 'text': 'Sbc'}), ('delete by visible index', [[['e0', 'a', True], ['e1', 'b', False], ['e2', 'c', False], ['e3', 'd', True], ['e4', 'e', False], ['e5', 'f', False]], [['delete', 0], ['delete', 2]]], {'ops': [['del', 'e1'], ['del', 'e5']], 'text': 'ce'}), ('delete last visible character', [[['e0', 'a', False], ['e1', 'b', False], ['e2', 'c', False], ['e3', 'd', True]], [['delete', 2]]], {'ops': [['del', 'e2']], 'text': 'ab'}), ('out-of-range edits are rejected', [[['e0', 'a', False], ['e1', 'b', False]], [['insert', 5, 'q'], ['delete', 2], ['delete', -1], ['insert', -1, 'r'], ['insert', 1, 'k']]], {'ops': [['reject', 5], ['reject', 2], ['reject', -1], ['reject', -1], ['ins', 'L1', 'e0']], 'text': 'akb'}), ('ids stay dense after a rejection', [[['e0', 'x', False], ['e1', 'y', False]], [['insert', 5, 'p'], ['insert', 1, 'm'], ['insert', 0, 'n']]], {'ops': [['reject', 5], ['ins', 'L1', 'e0'], ['ins', 'L2', None]], 'text': 'nxmy'}), ('typing into an empty document', [[], [['insert', 0, 'h'], ['insert', 1, 'i'], ['insert', 2, '!'], ['insert', 3, '!']]], {'ops': [['ins', 'L1', None], ['ins', 'L2', 'L1'], ['ins', 'L3', 'L2'], ['ins', 'L4', 'L3']], 'text': 'hi!!'}), ('mixed edits', [[['e0', 'h', False], ['e1', 'e', True], ['e2', 'l', False], ['e3', 'l', False], ['e4', 'o', False]], [['delete', 1], ['insert', 1, 'E'], ['insert', 4, '?']]], {'ops': [['del', 'e2'], ['ins', 'L1', 'e0'], ['ins', 'L2', 'e4']], 'text': 'hElo?'})],
3: [('insert after tombstones uses the visible neighbour', [[['e0', 'a', False], ['e1', 'b', True], ['e2', 'c', True], ['e3', 'd', False], ['e4', 'e', False]], [['insert', 2, 'X']]], {'ops': [['ins', 'L1', 'e3']], 'text': 'adXe'}), ('insert at the visible end', [[['e0', 'a', False], ['e1', 'b', False], ['e2', 'c', True]], [['insert', 2, 'Z'], ['insert', 3, 'W']]], {'ops': [['ins', 'L1', 'e1'], ['ins', 'L2', 'L1']], 'text': 'abZW'}), ('insert at the start', [[['e0', 'a', True], ['e1', 'b', False], ['e2', 'c', False]], [['insert', 0, 'S']]], {'ops': [['ins', 'L1', None]], 'text': 'Sbc'}), ('delete by visible index', [[['e0', 'a', True], ['e1', 'b', False], ['e2', 'c', False], ['e3', 'd', True], ['e4', 'e', False], ['e5', 'f', False]], [['delete', 0], ['delete', 2]]], {'ops': [['del', 'e1'], ['del', 'e5']], 'text': 'ce'}), ('delete last visible character', [[['e0', 'a', False], ['e1', 'b', False], ['e2', 'c', False], ['e3', 'd', True]], [['delete', 2]]], {'ops': [['del', 'e2']], 'text': 'ab'}), ('out-of-range edits are rejected', [[['e0', 'a', False], ['e1', 'b', False]], [['insert', 6, 'q'], ['delete', 2], ['delete', -1], ['insert', -1, 'r'], ['insert', 1, 'k']]], {'ops': [['reject', 6], ['reject', 2], ['reject', -1], ['reject', -1], ['ins', 'L1', 'e0']], 'text': 'akb'}), ('ids stay dense after a rejection', [[['e0', 'x', False], ['e1', 'y', False]], [['insert', 5, 'p'], ['insert', 1, 'm'], ['insert', 0, 'n']]], {'ops': [['reject', 5], ['ins', 'L1', 'e0'], ['ins', 'L2', None]], 'text': 'nxmy'}), ('typing into an empty document', [[], [['insert', 0, 'h'], ['insert', 1, 'i'], ['insert', 2, '!'], ['insert', 3, '!'], ['insert', 4, '!']]], {'ops': [['ins', 'L1', None], ['ins', 'L2', 'L1'], ['ins', 'L3', 'L2'], ['ins', 'L4', 'L3'], ['ins', 'L5', 'L4']], 'text': 'hi!!!'}), ('mixed edits', [[['e0', 'h', False], ['e1', 'e', True], ['e2', 'l', False], ['e3', 'l', False], ['e4', 'o', False]], [['delete', 1], ['insert', 1, 'E'], ['insert', 4, '?']]], {'ops': [['del', 'e2'], ['ins', 'L1', 'e0'], ['ins', 'L2', 'e4']], 'text': 'hElo?'})],
4: [('insert after tombstones uses the visible neighbour', [[['e0', 'a', False], ['e1', 'b', True], ['e2', 'c', True], ['e3', 'd', False], ['e4', 'e', False]], [['insert', 2, 'X']]], {'ops': [['ins', 'L1', 'e3']], 'text': 'adXe'}), ('insert at the visible end', [[['e0', 'a', False], ['e1', 'b', False], ['e2', 'c', True]], [['insert', 2, 'Z'], ['insert', 3, 'W']]], {'ops': [['ins', 'L1', 'e1'], ['ins', 'L2', 'L1']], 'text': 'abZW'}), ('insert at the start', [[['e0', 'a', True], ['e1', 'b', False], ['e2', 'c', False]], [['insert', 0, 'S']]], {'ops': [['ins', 'L1', None]], 'text': 'Sbc'}), ('delete by visible index', [[['e0', 'a', True], ['e1', 'b', False], ['e2', 'c', False], ['e3', 'd', True], ['e4', 'e', False], ['e5', 'f', False]], [['delete', 0], ['delete', 2]]], {'ops': [['del', 'e1'], ['del', 'e5']], 'text': 'ce'}), ('delete last visible character', [[['e0', 'a', False], ['e1', 'b', False], ['e2', 'c', False], ['e3', 'd', True]], [['delete', 2]]], {'ops': [['del', 'e2']], 'text': 'ab'}), ('out-of-range edits are rejected', [[['e0', 'a', False], ['e1', 'b', False]], [['insert', 7, 'q'], ['delete', 2], ['delete', -1], ['insert', -1, 'r'], ['insert', 1, 'k']]], {'ops': [['reject', 7], ['reject', 2], ['reject', -1], ['reject', -1], ['ins', 'L1', 'e0']], 'text': 'akb'}), ('ids stay dense after a rejection', [[['e0', 'x', False], ['e1', 'y', False]], [['insert', 5, 'p'], ['insert', 1, 'm'], ['insert', 0, 'n']]], {'ops': [['reject', 5], ['ins', 'L1', 'e0'], ['ins', 'L2', None]], 'text': 'nxmy'}), ('typing into an empty document', [[], [['insert', 0, 'h'], ['insert', 1, 'i'], ['insert', 2, '!'], ['insert', 3, '!'], ['insert', 4, '!'], ['insert', 5, '!']]], {'ops': [['ins', 'L1', None], ['ins', 'L2', 'L1'], ['ins', 'L3', 'L2'], ['ins', 'L4', 'L3'], ['ins', 'L5', 'L4'], ['ins', 'L6', 'L5']], 'text': 'hi!!!!'}), ('mixed edits', [[['e0', 'h', False], ['e1', 'e', True], ['e2', 'l', False], ['e3', 'l', False], ['e4', 'o', False]], [['delete', 1], ['insert', 1, 'E'], ['insert', 4, '?']]], {'ops': [['del', 'e2'], ['ins', 'L1', 'e0'], ['ins', 'L2', 'e4']], 'text': 'hElo?'})],
5: [('insert after tombstones uses the visible neighbour', [[['e0', 'a', False], ['e1', 'b', True], ['e2', 'c', True], ['e3', 'd', False], ['e4', 'e', False]], [['insert', 2, 'X']]], {'ops': [['ins', 'L1', 'e3']], 'text': 'adXe'}), ('insert at the visible end', [[['e0', 'a', False], ['e1', 'b', False], ['e2', 'c', True]], [['insert', 2, 'Z'], ['insert', 3, 'W']]], {'ops': [['ins', 'L1', 'e1'], ['ins', 'L2', 'L1']], 'text': 'abZW'}), ('insert at the start', [[['e0', 'a', True], ['e1', 'b', False], ['e2', 'c', False]], [['insert', 0, 'S']]], {'ops': [['ins', 'L1', None]], 'text': 'Sbc'}), ('delete by visible index', [[['e0', 'a', True], ['e1', 'b', False], ['e2', 'c', False], ['e3', 'd', True], ['e4', 'e', False], ['e5', 'f', False]], [['delete', 0], ['delete', 2]]], {'ops': [['del', 'e1'], ['del', 'e5']], 'text': 'ce'}), ('delete last visible character', [[['e0', 'a', False], ['e1', 'b', False], ['e2', 'c', False], ['e3', 'd', True]], [['delete', 2]]], {'ops': [['del', 'e2']], 'text': 'ab'}), ('out-of-range edits are rejected', [[['e0', 'a', False], ['e1', 'b', False]], [['insert', 8, 'q'], ['delete', 2], ['delete', -1], ['insert', -1, 'r'], ['insert', 1, 'k']]], {'ops': [['reject', 8], ['reject', 2], ['reject', -1], ['reject', -1], ['ins', 'L1', 'e0']], 'text': 'akb'}), ('ids stay dense after a rejection', [[['e0', 'x', False], ['e1', 'y', False]], [['insert', 5, 'p'], ['insert', 1, 'm'], ['insert', 0, 'n']]], {'ops': [['reject', 5], ['ins', 'L1', 'e0'], ['ins', 'L2', None]], 'text': 'nxmy'}), ('typing into an empty document', [[], [['insert', 0, 'h'], ['insert', 1, 'i'], ['insert', 2, '!'], ['insert', 3, '!'], ['insert', 4, '!'], ['insert', 5, '!'], ['insert', 6, '!']]], {'ops': [['ins', 'L1', None], ['ins', 'L2', 'L1'], ['ins', 'L3', 'L2'], ['ins', 'L4', 'L3'], ['ins', 'L5', 'L4'], ['ins', 'L6', 'L5'], ['ins', 'L7', 'L6']], 'text': 'hi!!!!!'}), ('mixed edits', [[['e0', 'h', False], ['e1', 'e', True], ['e2', 'l', False], ['e3', 'l', False], ['e4', 'o', False]], [['delete', 1], ['insert', 1, 'E'], ['insert', 4, '?']]], {'ops': [['del', 'e2'], ['ins', 'L1', 'e0'], ['ins', 'L2', 'e4']], 'text': 'hElo?'})],
}[N]
for label, args, expected in cases:
check(label, solve(*args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
| Boundary fixture | Actual | Expected | Outcome |
|---|---|---|---|
| insert after tombstones uses the visible neighbour | {'ops': [['ins', 'L1', 'e3']], 'text': 'adXe'} | {'ops': [['ins', 'L1', 'e3']], 'text': 'adXe'} | Passed |
| insert at the visible end | {'ops': [['ins', 'L1', 'e1'], ['ins', 'L2', 'L1']], 'text': 'abZW'} | {'ops': [['ins', 'L1', 'e1'], ['ins', 'L2', 'L1']], 'text': 'abZW'} | Passed |
| insert at the start | {'ops': [['ins', 'L1', None]], 'text': 'Sbc'} | {'ops': [['ins', 'L1', None]], 'text': 'Sbc'} | Passed |
| delete by visible index | {'ops': [['del', 'e5'], ['del', 'e2']], 'text': 'be'} | {'ops': [['del', 'e1'], ['del', 'e5']], 'text': 'ce'} | Failed |
| delete last visible character | {'ops': [['del', 'e1']], 'text': 'ac'} | {'ops': [['del', 'e2']], 'text': 'ab'} | Failed |
| out-of-range edits are rejected | {'ops': [['reject', 4], ['reject', 2], ['reject', -1], ['reject', -1], ['ins', 'L1', 'e0']], 'text': 'akb'} | {'ops': [['reject', 4], ['reject', 2], ['reject', -1], ['reject', -1], ['ins', 'L1', 'e0']], 'text': 'akb'} | Passed |
| ids stay dense after a rejection | {'ops': [['reject', 5], ['ins', 'L1', 'e0'], ['ins', 'L2', None]], 'text': 'nxmy'} | {'ops': [['reject', 5], ['ins', 'L1', 'e0'], ['ins', 'L2', None]], 'text': 'nxmy'} | Passed |
| typing into an empty document | {'ops': [['ins', 'L1', None], ['ins', 'L2', 'L1'], ['ins', 'L3', 'L2']], 'text': 'hi!'} | {'ops': [['ins', 'L1', None], ['ins', 'L2', 'L1'], ['ins', 'L3', 'L2']], 'text': 'hi!'} | Passed |
| mixed edits | {'ops': [['del', 'e0'], ['ins', 'L1', 'e2'], ['ins', 'L2', 'e4']], 'text': 'lElo?'} | {'ops': [['del', 'e2'], ['ins', 'L1', 'e0'], ['ins', 'L2', 'e4']], 'text': 'hElo?'} | Failed |
SHA-256 / 0362b32593681f00027fa72ecb07dfb72dba31cbefd158674f0bf9cd284ea884
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(elements, edits):
seq = [list(e) for e in elements]
out = []
k = 0
for ed in edits:
vis = [i for i, e in enumerate(seq) if not e[2]]
idx = ed[1]
if ed[0] == 'insert':
if idx < 0 or idx > len(vis):
out.append(['reject', idx])
continue
if idx == 0:
after, pos = None, 0
else:
p = vis[idx - 1]
after, pos = seq[p][0], p + 1
k += 1
nid = 'L%d' % k
seq.insert(pos, [nid, ed[2], False])
out.append(['ins', nid, after])
else:
if idx < 0 or idx >= len(vis):
out.append(['reject', idx])
continue
p = vis[max(idx - 1, 0)]
seq[p][2] = True
out.append(['del', seq[p][0]])
return {'ops': out, 'text': ''.join(e[1] for e in seq if not e[2])}
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
cases = {
1: [('insert after tombstones uses the visible neighbour', [[['e0', 'a', False], ['e1', 'b', True], ['e2', 'c', True], ['e3', 'd', False], ['e4', 'e', False]], [['insert', 2, 'X']]], {'ops': [['ins', 'L1', 'e3']], 'text': 'adXe'}), ('insert at the visible end', [[['e0', 'a', False], ['e1', 'b', False], ['e2', 'c', True]], [['insert', 2, 'Z'], ['insert', 3, 'W']]], {'ops': [['ins', 'L1', 'e1'], ['ins', 'L2', 'L1']], 'text': 'abZW'}), ('insert at the start', [[['e0', 'a', True], ['e1', 'b', False], ['e2', 'c', False]], [['insert', 0, 'S']]], {'ops': [['ins', 'L1', None]], 'text': 'Sbc'}), ('delete by visible index', [[['e0', 'a', True], ['e1', 'b', False], ['e2', 'c', False], ['e3', 'd', True], ['e4', 'e', False], ['e5', 'f', False]], [['delete', 0], ['delete', 2]]], {'ops': [['del', 'e1'], ['del', 'e5']], 'text': 'ce'}), ('delete last visible character', [[['e0', 'a', False], ['e1', 'b', False], ['e2', 'c', False], ['e3', 'd', True]], [['delete', 2]]], {'ops': [['del', 'e2']], 'text': 'ab'}), ('out-of-range edits are rejected', [[['e0', 'a', False], ['e1', 'b', False]], [['insert', 4, 'q'], ['delete', 2], ['delete', -1], ['insert', -1, 'r'], ['insert', 1, 'k']]], {'ops': [['reject', 4], ['reject', 2], ['reject', -1], ['reject', -1], ['ins', 'L1', 'e0']], 'text': 'akb'}), ('ids stay dense after a rejection', [[['e0', 'x', False], ['e1', 'y', False]], [['insert', 5, 'p'], ['insert', 1, 'm'], ['insert', 0, 'n']]], {'ops': [['reject', 5], ['ins', 'L1', 'e0'], ['ins', 'L2', None]], 'text': 'nxmy'}), ('typing into an empty document', [[], [['insert', 0, 'h'], ['insert', 1, 'i'], ['insert', 2, '!']]], {'ops': [['ins', 'L1', None], ['ins', 'L2', 'L1'], ['ins', 'L3', 'L2']], 'text': 'hi!'}), ('mixed edits', [[['e0', 'h', False], ['e1', 'e', True], ['e2', 'l', False], ['e3', 'l', False], ['e4', 'o', False]], [['delete', 1], ['insert', 1, 'E'], ['insert', 4, '?']]], {'ops': [['del', 'e2'], ['ins', 'L1', 'e0'], ['ins', 'L2', 'e4']], 'text': 'hElo?'})],
2: [('insert after tombstones uses the visible neighbour', [[['e0', 'a', False], ['e1', 'b', True], ['e2', 'c', True], ['e3', 'd', False], ['e4', 'e', False]], [['insert', 2, 'X']]], {'ops': [['ins', 'L1', 'e3']], 'text': 'adXe'}), ('insert at the visible end', [[['e0', 'a', False], ['e1', 'b', False], ['e2', 'c', True]], [['insert', 2, 'Z'], ['insert', 3, 'W']]], {'ops': [['ins', 'L1', 'e1'], ['ins', 'L2', 'L1']], 'text': 'abZW'}), ('insert at the start', [[['e0', 'a', True], ['e1', 'b', False], ['e2', 'c', False]], [['insert', 0, 'S']]], {'ops': [['ins', 'L1', None]], 'text': 'Sbc'}), ('delete by visible index', [[['e0', 'a', True], ['e1', 'b', False], ['e2', 'c', False], ['e3', 'd', True], ['e4', 'e', False], ['e5', 'f', False]], [['delete', 0], ['delete', 2]]], {'ops': [['del', 'e1'], ['del', 'e5']], 'text': 'ce'}), ('delete last visible character', [[['e0', 'a', False], ['e1', 'b', False], ['e2', 'c', False], ['e3', 'd', True]], [['delete', 2]]], {'ops': [['del', 'e2']], 'text': 'ab'}), ('out-of-range edits are rejected', [[['e0', 'a', False], ['e1', 'b', False]], [['insert', 5, 'q'], ['delete', 2], ['delete', -1], ['insert', -1, 'r'], ['insert', 1, 'k']]], {'ops': [['reject', 5], ['reject', 2], ['reject', -1], ['reject', -1], ['ins', 'L1', 'e0']], 'text': 'akb'}), ('ids stay dense after a rejection', [[['e0', 'x', False], ['e1', 'y', False]], [['insert', 5, 'p'], ['insert', 1, 'm'], ['insert', 0, 'n']]], {'ops': [['reject', 5], ['ins', 'L1', 'e0'], ['ins', 'L2', None]], 'text': 'nxmy'}), ('typing into an empty document', [[], [['insert', 0, 'h'], ['insert', 1, 'i'], ['insert', 2, '!'], ['insert', 3, '!']]], {'ops': [['ins', 'L1', None], ['ins', 'L2', 'L1'], ['ins', 'L3', 'L2'], ['ins', 'L4', 'L3']], 'text': 'hi!!'}), ('mixed edits', [[['e0', 'h', False], ['e1', 'e', True], ['e2', 'l', False], ['e3', 'l', False], ['e4', 'o', False]], [['delete', 1], ['insert', 1, 'E'], ['insert', 4, '?']]], {'ops': [['del', 'e2'], ['ins', 'L1', 'e0'], ['ins', 'L2', 'e4']], 'text': 'hElo?'})],
3: [('insert after tombstones uses the visible neighbour', [[['e0', 'a', False], ['e1', 'b', True], ['e2', 'c', True], ['e3', 'd', False], ['e4', 'e', False]], [['insert', 2, 'X']]], {'ops': [['ins', 'L1', 'e3']], 'text': 'adXe'}), ('insert at the visible end', [[['e0', 'a', False], ['e1', 'b', False], ['e2', 'c', True]], [['insert', 2, 'Z'], ['insert', 3, 'W']]], {'ops': [['ins', 'L1', 'e1'], ['ins', 'L2', 'L1']], 'text': 'abZW'}), ('insert at the start', [[['e0', 'a', True], ['e1', 'b', False], ['e2', 'c', False]], [['insert', 0, 'S']]], {'ops': [['ins', 'L1', None]], 'text': 'Sbc'}), ('delete by visible index', [[['e0', 'a', True], ['e1', 'b', False], ['e2', 'c', False], ['e3', 'd', True], ['e4', 'e', False], ['e5', 'f', False]], [['delete', 0], ['delete', 2]]], {'ops': [['del', 'e1'], ['del', 'e5']], 'text': 'ce'}), ('delete last visible character', [[['e0', 'a', False], ['e1', 'b', False], ['e2', 'c', False], ['e3', 'd', True]], [['delete', 2]]], {'ops': [['del', 'e2']], 'text': 'ab'}), ('out-of-range edits are rejected', [[['e0', 'a', False], ['e1', 'b', False]], [['insert', 6, 'q'], ['delete', 2], ['delete', -1], ['insert', -1, 'r'], ['insert', 1, 'k']]], {'ops': [['reject', 6], ['reject', 2], ['reject', -1], ['reject', -1], ['ins', 'L1', 'e0']], 'text': 'akb'}), ('ids stay dense after a rejection', [[['e0', 'x', False], ['e1', 'y', False]], [['insert', 5, 'p'], ['insert', 1, 'm'], ['insert', 0, 'n']]], {'ops': [['reject', 5], ['ins', 'L1', 'e0'], ['ins', 'L2', None]], 'text': 'nxmy'}), ('typing into an empty document', [[], [['insert', 0, 'h'], ['insert', 1, 'i'], ['insert', 2, '!'], ['insert', 3, '!'], ['insert', 4, '!']]], {'ops': [['ins', 'L1', None], ['ins', 'L2', 'L1'], ['ins', 'L3', 'L2'], ['ins', 'L4', 'L3'], ['ins', 'L5', 'L4']], 'text': 'hi!!!'}), ('mixed edits', [[['e0', 'h', False], ['e1', 'e', True], ['e2', 'l', False], ['e3', 'l', False], ['e4', 'o', False]], [['delete', 1], ['insert', 1, 'E'], ['insert', 4, '?']]], {'ops': [['del', 'e2'], ['ins', 'L1', 'e0'], ['ins', 'L2', 'e4']], 'text': 'hElo?'})],
4: [('insert after tombstones uses the visible neighbour', [[['e0', 'a', False], ['e1', 'b', True], ['e2', 'c', True], ['e3', 'd', False], ['e4', 'e', False]], [['insert', 2, 'X']]], {'ops': [['ins', 'L1', 'e3']], 'text': 'adXe'}), ('insert at the visible end', [[['e0', 'a', False], ['e1', 'b', False], ['e2', 'c', True]], [['insert', 2, 'Z'], ['insert', 3, 'W']]], {'ops': [['ins', 'L1', 'e1'], ['ins', 'L2', 'L1']], 'text': 'abZW'}), ('insert at the start', [[['e0', 'a', True], ['e1', 'b', False], ['e2', 'c', False]], [['insert', 0, 'S']]], {'ops': [['ins', 'L1', None]], 'text': 'Sbc'}), ('delete by visible index', [[['e0', 'a', True], ['e1', 'b', False], ['e2', 'c', False], ['e3', 'd', True], ['e4', 'e', False], ['e5', 'f', False]], [['delete', 0], ['delete', 2]]], {'ops': [['del', 'e1'], ['del', 'e5']], 'text': 'ce'}), ('delete last visible character', [[['e0', 'a', False], ['e1', 'b', False], ['e2', 'c', False], ['e3', 'd', True]], [['delete', 2]]], {'ops': [['del', 'e2']], 'text': 'ab'}), ('out-of-range edits are rejected', [[['e0', 'a', False], ['e1', 'b', False]], [['insert', 7, 'q'], ['delete', 2], ['delete', -1], ['insert', -1, 'r'], ['insert', 1, 'k']]], {'ops': [['reject', 7], ['reject', 2], ['reject', -1], ['reject', -1], ['ins', 'L1', 'e0']], 'text': 'akb'}), ('ids stay dense after a rejection', [[['e0', 'x', False], ['e1', 'y', False]], [['insert', 5, 'p'], ['insert', 1, 'm'], ['insert', 0, 'n']]], {'ops': [['reject', 5], ['ins', 'L1', 'e0'], ['ins', 'L2', None]], 'text': 'nxmy'}), ('typing into an empty document', [[], [['insert', 0, 'h'], ['insert', 1, 'i'], ['insert', 2, '!'], ['insert', 3, '!'], ['insert', 4, '!'], ['insert', 5, '!']]], {'ops': [['ins', 'L1', None], ['ins', 'L2', 'L1'], ['ins', 'L3', 'L2'], ['ins', 'L4', 'L3'], ['ins', 'L5', 'L4'], ['ins', 'L6', 'L5']], 'text': 'hi!!!!'}), ('mixed edits', [[['e0', 'h', False], ['e1', 'e', True], ['e2', 'l', False], ['e3', 'l', False], ['e4', 'o', False]], [['delete', 1], ['insert', 1, 'E'], ['insert', 4, '?']]], {'ops': [['del', 'e2'], ['ins', 'L1', 'e0'], ['ins', 'L2', 'e4']], 'text': 'hElo?'})],
5: [('insert after tombstones uses the visible neighbour', [[['e0', 'a', False], ['e1', 'b', True], ['e2', 'c', True], ['e3', 'd', False], ['e4', 'e', False]], [['insert', 2, 'X']]], {'ops': [['ins', 'L1', 'e3']], 'text': 'adXe'}), ('insert at the visible end', [[['e0', 'a', False], ['e1', 'b', False], ['e2', 'c', True]], [['insert', 2, 'Z'], ['insert', 3, 'W']]], {'ops': [['ins', 'L1', 'e1'], ['ins', 'L2', 'L1']], 'text': 'abZW'}), ('insert at the start', [[['e0', 'a', True], ['e1', 'b', False], ['e2', 'c', False]], [['insert', 0, 'S']]], {'ops': [['ins', 'L1', None]], 'text': 'Sbc'}), ('delete by visible index', [[['e0', 'a', True], ['e1', 'b', False], ['e2', 'c', False], ['e3', 'd', True], ['e4', 'e', False], ['e5', 'f', False]], [['delete', 0], ['delete', 2]]], {'ops': [['del', 'e1'], ['del', 'e5']], 'text': 'ce'}), ('delete last visible character', [[['e0', 'a', False], ['e1', 'b', False], ['e2', 'c', False], ['e3', 'd', True]], [['delete', 2]]], {'ops': [['del', 'e2']], 'text': 'ab'}), ('out-of-range edits are rejected', [[['e0', 'a', False], ['e1', 'b', False]], [['insert', 8, 'q'], ['delete', 2], ['delete', -1], ['insert', -1, 'r'], ['insert', 1, 'k']]], {'ops': [['reject', 8], ['reject', 2], ['reject', -1], ['reject', -1], ['ins', 'L1', 'e0']], 'text': 'akb'}), ('ids stay dense after a rejection', [[['e0', 'x', False], ['e1', 'y', False]], [['insert', 5, 'p'], ['insert', 1, 'm'], ['insert', 0, 'n']]], {'ops': [['reject', 5], ['ins', 'L1', 'e0'], ['ins', 'L2', None]], 'text': 'nxmy'}), ('typing into an empty document', [[], [['insert', 0, 'h'], ['insert', 1, 'i'], ['insert', 2, '!'], ['insert', 3, '!'], ['insert', 4, '!'], ['insert', 5, '!'], ['insert', 6, '!']]], {'ops': [['ins', 'L1', None], ['ins', 'L2', 'L1'], ['ins', 'L3', 'L2'], ['ins', 'L4', 'L3'], ['ins', 'L5', 'L4'], ['ins', 'L6', 'L5'], ['ins', 'L7', 'L6']], 'text': 'hi!!!!!'}), ('mixed edits', [[['e0', 'h', False], ['e1', 'e', True], ['e2', 'l', False], ['e3', 'l', False], ['e4', 'o', False]], [['delete', 1], ['insert', 1, 'E'], ['insert', 4, '?']]], {'ops': [['del', 'e2'], ['ins', 'L1', 'e0'], ['ins', 'L2', 'e4']], 'text': 'hElo?'})],
}[N]
for label, args, expected in cases:
check(label, solve(*args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
| Boundary fixture | Actual | Expected | Outcome |
|---|---|---|---|
| insert after tombstones uses the visible neighbour | {'ops': [['ins', 'L1', 'e3']], 'text': 'adXe'} | {'ops': [['ins', 'L1', 'e3']], 'text': 'adXe'} | Passed |
| insert at the visible end | {'ops': [['ins', 'L1', 'e1'], ['ins', 'L2', 'L1']], 'text': 'abZW'} | {'ops': [['ins', 'L1', 'e1'], ['ins', 'L2', 'L1']], 'text': 'abZW'} | Passed |
| insert at the start | {'ops': [['ins', 'L1', None]], 'text': 'Sbc'} | {'ops': [['ins', 'L1', None]], 'text': 'Sbc'} | Passed |
| delete by visible index | {'ops': [['del', 'e1'], ['del', 'e4']], 'text': 'cf'} | {'ops': [['del', 'e1'], ['del', 'e5']], 'text': 'ce'} | Failed |
| delete last visible character | {'ops': [['del', 'e1']], 'text': 'ac'} | {'ops': [['del', 'e2']], 'text': 'ab'} | Failed |
| out-of-range edits are rejected | {'ops': [['reject', 4], ['reject', 2], ['reject', -1], ['reject', -1], ['ins', 'L1', 'e0']], 'text': 'akb'} | {'ops': [['reject', 4], ['reject', 2], ['reject', -1], ['reject', -1], ['ins', 'L1', 'e0']], 'text': 'akb'} | Passed |
| ids stay dense after a rejection | {'ops': [['reject', 5], ['ins', 'L1', 'e0'], ['ins', 'L2', None]], 'text': 'nxmy'} | {'ops': [['reject', 5], ['ins', 'L1', 'e0'], ['ins', 'L2', None]], 'text': 'nxmy'} | Passed |
| typing into an empty document | {'ops': [['ins', 'L1', None], ['ins', 'L2', 'L1'], ['ins', 'L3', 'L2']], 'text': 'hi!'} | {'ops': [['ins', 'L1', None], ['ins', 'L2', 'L1'], ['ins', 'L3', 'L2']], 'text': 'hi!'} | Passed |
| mixed edits | {'ops': [['del', 'e0'], ['ins', 'L1', 'e2'], ['ins', 'L2', 'e4']], 'text': 'lElo?'} | {'ops': [['del', 'e2'], ['ins', 'L1', 'e0'], ['ins', 'L2', 'e4']], 'text': 'hElo?'} | Failed |
SHA-256 / f8d94429bec156395c7e908ac913d82ae0a9c4c87ad8b0f86f67fe8bfdaabd72
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(elements, edits):
seq = [list(e) for e in elements]
out = []
k = 0
for ed in edits:
vis = [i for i, e in enumerate(seq) if not e[2]]
idx = ed[1]
if ed[0] == 'insert':
if idx < 0 or idx > len(vis):
out.append(['reject', idx])
continue
if idx == 0:
after, pos = None, 0
else:
p = vis[idx - 1]
after, pos = seq[p][0], p + 1
k += 1
nid = 'L%d' % k
seq.insert(pos, [nid, ed[2], False])
out.append(['ins', nid, after])
else:
if idx < 0 or idx >= len(vis):
out.append(['reject', idx])
continue
p = vis[idx]
seq[p][2] = True
out.append(['del', seq[p][0]])
return {'ops': out, 'text': ''.join(e[1] for e in seq if not e[2])}
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
cases = {
1: [('insert after tombstones uses the visible neighbour', [[['e0', 'a', False], ['e1', 'b', True], ['e2', 'c', True], ['e3', 'd', False], ['e4', 'e', False]], [['insert', 2, 'X']]], {'ops': [['ins', 'L1', 'e3']], 'text': 'adXe'}), ('insert at the visible end', [[['e0', 'a', False], ['e1', 'b', False], ['e2', 'c', True]], [['insert', 2, 'Z'], ['insert', 3, 'W']]], {'ops': [['ins', 'L1', 'e1'], ['ins', 'L2', 'L1']], 'text': 'abZW'}), ('insert at the start', [[['e0', 'a', True], ['e1', 'b', False], ['e2', 'c', False]], [['insert', 0, 'S']]], {'ops': [['ins', 'L1', None]], 'text': 'Sbc'}), ('delete by visible index', [[['e0', 'a', True], ['e1', 'b', False], ['e2', 'c', False], ['e3', 'd', True], ['e4', 'e', False], ['e5', 'f', False]], [['delete', 0], ['delete', 2]]], {'ops': [['del', 'e1'], ['del', 'e5']], 'text': 'ce'}), ('delete last visible character', [[['e0', 'a', False], ['e1', 'b', False], ['e2', 'c', False], ['e3', 'd', True]], [['delete', 2]]], {'ops': [['del', 'e2']], 'text': 'ab'}), ('out-of-range edits are rejected', [[['e0', 'a', False], ['e1', 'b', False]], [['insert', 4, 'q'], ['delete', 2], ['delete', -1], ['insert', -1, 'r'], ['insert', 1, 'k']]], {'ops': [['reject', 4], ['reject', 2], ['reject', -1], ['reject', -1], ['ins', 'L1', 'e0']], 'text': 'akb'}), ('ids stay dense after a rejection', [[['e0', 'x', False], ['e1', 'y', False]], [['insert', 5, 'p'], ['insert', 1, 'm'], ['insert', 0, 'n']]], {'ops': [['reject', 5], ['ins', 'L1', 'e0'], ['ins', 'L2', None]], 'text': 'nxmy'}), ('typing into an empty document', [[], [['insert', 0, 'h'], ['insert', 1, 'i'], ['insert', 2, '!']]], {'ops': [['ins', 'L1', None], ['ins', 'L2', 'L1'], ['ins', 'L3', 'L2']], 'text': 'hi!'}), ('mixed edits', [[['e0', 'h', False], ['e1', 'e', True], ['e2', 'l', False], ['e3', 'l', False], ['e4', 'o', False]], [['delete', 1], ['insert', 1, 'E'], ['insert', 4, '?']]], {'ops': [['del', 'e2'], ['ins', 'L1', 'e0'], ['ins', 'L2', 'e4']], 'text': 'hElo?'})],
2: [('insert after tombstones uses the visible neighbour', [[['e0', 'a', False], ['e1', 'b', True], ['e2', 'c', True], ['e3', 'd', False], ['e4', 'e', False]], [['insert', 2, 'X']]], {'ops': [['ins', 'L1', 'e3']], 'text': 'adXe'}), ('insert at the visible end', [[['e0', 'a', False], ['e1', 'b', False], ['e2', 'c', True]], [['insert', 2, 'Z'], ['insert', 3, 'W']]], {'ops': [['ins', 'L1', 'e1'], ['ins', 'L2', 'L1']], 'text': 'abZW'}), ('insert at the start', [[['e0', 'a', True], ['e1', 'b', False], ['e2', 'c', False]], [['insert', 0, 'S']]], {'ops': [['ins', 'L1', None]], 'text': 'Sbc'}), ('delete by visible index', [[['e0', 'a', True], ['e1', 'b', False], ['e2', 'c', False], ['e3', 'd', True], ['e4', 'e', False], ['e5', 'f', False]], [['delete', 0], ['delete', 2]]], {'ops': [['del', 'e1'], ['del', 'e5']], 'text': 'ce'}), ('delete last visible character', [[['e0', 'a', False], ['e1', 'b', False], ['e2', 'c', False], ['e3', 'd', True]], [['delete', 2]]], {'ops': [['del', 'e2']], 'text': 'ab'}), ('out-of-range edits are rejected', [[['e0', 'a', False], ['e1', 'b', False]], [['insert', 5, 'q'], ['delete', 2], ['delete', -1], ['insert', -1, 'r'], ['insert', 1, 'k']]], {'ops': [['reject', 5], ['reject', 2], ['reject', -1], ['reject', -1], ['ins', 'L1', 'e0']], 'text': 'akb'}), ('ids stay dense after a rejection', [[['e0', 'x', False], ['e1', 'y', False]], [['insert', 5, 'p'], ['insert', 1, 'm'], ['insert', 0, 'n']]], {'ops': [['reject', 5], ['ins', 'L1', 'e0'], ['ins', 'L2', None]], 'text': 'nxmy'}), ('typing into an empty document', [[], [['insert', 0, 'h'], ['insert', 1, 'i'], ['insert', 2, '!'], ['insert', 3, '!']]], {'ops': [['ins', 'L1', None], ['ins', 'L2', 'L1'], ['ins', 'L3', 'L2'], ['ins', 'L4', 'L3']], 'text': 'hi!!'}), ('mixed edits', [[['e0', 'h', False], ['e1', 'e', True], ['e2', 'l', False], ['e3', 'l', False], ['e4', 'o', False]], [['delete', 1], ['insert', 1, 'E'], ['insert', 4, '?']]], {'ops': [['del', 'e2'], ['ins', 'L1', 'e0'], ['ins', 'L2', 'e4']], 'text': 'hElo?'})],
3: [('insert after tombstones uses the visible neighbour', [[['e0', 'a', False], ['e1', 'b', True], ['e2', 'c', True], ['e3', 'd', False], ['e4', 'e', False]], [['insert', 2, 'X']]], {'ops': [['ins', 'L1', 'e3']], 'text': 'adXe'}), ('insert at the visible end', [[['e0', 'a', False], ['e1', 'b', False], ['e2', 'c', True]], [['insert', 2, 'Z'], ['insert', 3, 'W']]], {'ops': [['ins', 'L1', 'e1'], ['ins', 'L2', 'L1']], 'text': 'abZW'}), ('insert at the start', [[['e0', 'a', True], ['e1', 'b', False], ['e2', 'c', False]], [['insert', 0, 'S']]], {'ops': [['ins', 'L1', None]], 'text': 'Sbc'}), ('delete by visible index', [[['e0', 'a', True], ['e1', 'b', False], ['e2', 'c', False], ['e3', 'd', True], ['e4', 'e', False], ['e5', 'f', False]], [['delete', 0], ['delete', 2]]], {'ops': [['del', 'e1'], ['del', 'e5']], 'text': 'ce'}), ('delete last visible character', [[['e0', 'a', False], ['e1', 'b', False], ['e2', 'c', False], ['e3', 'd', True]], [['delete', 2]]], {'ops': [['del', 'e2']], 'text': 'ab'}), ('out-of-range edits are rejected', [[['e0', 'a', False], ['e1', 'b', False]], [['insert', 6, 'q'], ['delete', 2], ['delete', -1], ['insert', -1, 'r'], ['insert', 1, 'k']]], {'ops': [['reject', 6], ['reject', 2], ['reject', -1], ['reject', -1], ['ins', 'L1', 'e0']], 'text': 'akb'}), ('ids stay dense after a rejection', [[['e0', 'x', False], ['e1', 'y', False]], [['insert', 5, 'p'], ['insert', 1, 'm'], ['insert', 0, 'n']]], {'ops': [['reject', 5], ['ins', 'L1', 'e0'], ['ins', 'L2', None]], 'text': 'nxmy'}), ('typing into an empty document', [[], [['insert', 0, 'h'], ['insert', 1, 'i'], ['insert', 2, '!'], ['insert', 3, '!'], ['insert', 4, '!']]], {'ops': [['ins', 'L1', None], ['ins', 'L2', 'L1'], ['ins', 'L3', 'L2'], ['ins', 'L4', 'L3'], ['ins', 'L5', 'L4']], 'text': 'hi!!!'}), ('mixed edits', [[['e0', 'h', False], ['e1', 'e', True], ['e2', 'l', False], ['e3', 'l', False], ['e4', 'o', False]], [['delete', 1], ['insert', 1, 'E'], ['insert', 4, '?']]], {'ops': [['del', 'e2'], ['ins', 'L1', 'e0'], ['ins', 'L2', 'e4']], 'text': 'hElo?'})],
4: [('insert after tombstones uses the visible neighbour', [[['e0', 'a', False], ['e1', 'b', True], ['e2', 'c', True], ['e3', 'd', False], ['e4', 'e', False]], [['insert', 2, 'X']]], {'ops': [['ins', 'L1', 'e3']], 'text': 'adXe'}), ('insert at the visible end', [[['e0', 'a', False], ['e1', 'b', False], ['e2', 'c', True]], [['insert', 2, 'Z'], ['insert', 3, 'W']]], {'ops': [['ins', 'L1', 'e1'], ['ins', 'L2', 'L1']], 'text': 'abZW'}), ('insert at the start', [[['e0', 'a', True], ['e1', 'b', False], ['e2', 'c', False]], [['insert', 0, 'S']]], {'ops': [['ins', 'L1', None]], 'text': 'Sbc'}), ('delete by visible index', [[['e0', 'a', True], ['e1', 'b', False], ['e2', 'c', False], ['e3', 'd', True], ['e4', 'e', False], ['e5', 'f', False]], [['delete', 0], ['delete', 2]]], {'ops': [['del', 'e1'], ['del', 'e5']], 'text': 'ce'}), ('delete last visible character', [[['e0', 'a', False], ['e1', 'b', False], ['e2', 'c', False], ['e3', 'd', True]], [['delete', 2]]], {'ops': [['del', 'e2']], 'text': 'ab'}), ('out-of-range edits are rejected', [[['e0', 'a', False], ['e1', 'b', False]], [['insert', 7, 'q'], ['delete', 2], ['delete', -1], ['insert', -1, 'r'], ['insert', 1, 'k']]], {'ops': [['reject', 7], ['reject', 2], ['reject', -1], ['reject', -1], ['ins', 'L1', 'e0']], 'text': 'akb'}), ('ids stay dense after a rejection', [[['e0', 'x', False], ['e1', 'y', False]], [['insert', 5, 'p'], ['insert', 1, 'm'], ['insert', 0, 'n']]], {'ops': [['reject', 5], ['ins', 'L1', 'e0'], ['ins', 'L2', None]], 'text': 'nxmy'}), ('typing into an empty document', [[], [['insert', 0, 'h'], ['insert', 1, 'i'], ['insert', 2, '!'], ['insert', 3, '!'], ['insert', 4, '!'], ['insert', 5, '!']]], {'ops': [['ins', 'L1', None], ['ins', 'L2', 'L1'], ['ins', 'L3', 'L2'], ['ins', 'L4', 'L3'], ['ins', 'L5', 'L4'], ['ins', 'L6', 'L5']], 'text': 'hi!!!!'}), ('mixed edits', [[['e0', 'h', False], ['e1', 'e', True], ['e2', 'l', False], ['e3', 'l', False], ['e4', 'o', False]], [['delete', 1], ['insert', 1, 'E'], ['insert', 4, '?']]], {'ops': [['del', 'e2'], ['ins', 'L1', 'e0'], ['ins', 'L2', 'e4']], 'text': 'hElo?'})],
5: [('insert after tombstones uses the visible neighbour', [[['e0', 'a', False], ['e1', 'b', True], ['e2', 'c', True], ['e3', 'd', False], ['e4', 'e', False]], [['insert', 2, 'X']]], {'ops': [['ins', 'L1', 'e3']], 'text': 'adXe'}), ('insert at the visible end', [[['e0', 'a', False], ['e1', 'b', False], ['e2', 'c', True]], [['insert', 2, 'Z'], ['insert', 3, 'W']]], {'ops': [['ins', 'L1', 'e1'], ['ins', 'L2', 'L1']], 'text': 'abZW'}), ('insert at the start', [[['e0', 'a', True], ['e1', 'b', False], ['e2', 'c', False]], [['insert', 0, 'S']]], {'ops': [['ins', 'L1', None]], 'text': 'Sbc'}), ('delete by visible index', [[['e0', 'a', True], ['e1', 'b', False], ['e2', 'c', False], ['e3', 'd', True], ['e4', 'e', False], ['e5', 'f', False]], [['delete', 0], ['delete', 2]]], {'ops': [['del', 'e1'], ['del', 'e5']], 'text': 'ce'}), ('delete last visible character', [[['e0', 'a', False], ['e1', 'b', False], ['e2', 'c', False], ['e3', 'd', True]], [['delete', 2]]], {'ops': [['del', 'e2']], 'text': 'ab'}), ('out-of-range edits are rejected', [[['e0', 'a', False], ['e1', 'b', False]], [['insert', 8, 'q'], ['delete', 2], ['delete', -1], ['insert', -1, 'r'], ['insert', 1, 'k']]], {'ops': [['reject', 8], ['reject', 2], ['reject', -1], ['reject', -1], ['ins', 'L1', 'e0']], 'text': 'akb'}), ('ids stay dense after a rejection', [[['e0', 'x', False], ['e1', 'y', False]], [['insert', 5, 'p'], ['insert', 1, 'm'], ['insert', 0, 'n']]], {'ops': [['reject', 5], ['ins', 'L1', 'e0'], ['ins', 'L2', None]], 'text': 'nxmy'}), ('typing into an empty document', [[], [['insert', 0, 'h'], ['insert', 1, 'i'], ['insert', 2, '!'], ['insert', 3, '!'], ['insert', 4, '!'], ['insert', 5, '!'], ['insert', 6, '!']]], {'ops': [['ins', 'L1', None], ['ins', 'L2', 'L1'], ['ins', 'L3', 'L2'], ['ins', 'L4', 'L3'], ['ins', 'L5', 'L4'], ['ins', 'L6', 'L5'], ['ins', 'L7', 'L6']], 'text': 'hi!!!!!'}), ('mixed edits', [[['e0', 'h', False], ['e1', 'e', True], ['e2', 'l', False], ['e3', 'l', False], ['e4', 'o', False]], [['delete', 1], ['insert', 1, 'E'], ['insert', 4, '?']]], {'ops': [['del', 'e2'], ['ins', 'L1', 'e0'], ['ins', 'L2', 'e4']], 'text': 'hElo?'})],
}[N]
for label, args, expected in cases:
check(label, solve(*args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
| Boundary fixture | Actual | Expected | Outcome |
|---|---|---|---|
| insert after tombstones uses the visible neighbour | {'ops': [['ins', 'L1', 'e3']], 'text': 'adXe'} | {'ops': [['ins', 'L1', 'e3']], 'text': 'adXe'} | Passed |
| insert at the visible end | {'ops': [['ins', 'L1', 'e1'], ['ins', 'L2', 'L1']], 'text': 'abZW'} | {'ops': [['ins', 'L1', 'e1'], ['ins', 'L2', 'L1']], 'text': 'abZW'} | Passed |
| insert at the start | {'ops': [['ins', 'L1', None]], 'text': 'Sbc'} | {'ops': [['ins', 'L1', None]], 'text': 'Sbc'} | Passed |
| delete by visible index | {'ops': [['del', 'e1'], ['del', 'e5']], 'text': 'ce'} | {'ops': [['del', 'e1'], ['del', 'e5']], 'text': 'ce'} | Passed |
| delete last visible character | {'ops': [['del', 'e2']], 'text': 'ab'} | {'ops': [['del', 'e2']], 'text': 'ab'} | Passed |
| out-of-range edits are rejected | {'ops': [['reject', 4], ['reject', 2], ['reject', -1], ['reject', -1], ['ins', 'L1', 'e0']], 'text': 'akb'} | {'ops': [['reject', 4], ['reject', 2], ['reject', -1], ['reject', -1], ['ins', 'L1', 'e0']], 'text': 'akb'} | Passed |
| ids stay dense after a rejection | {'ops': [['reject', 5], ['ins', 'L1', 'e0'], ['ins', 'L2', None]], 'text': 'nxmy'} | {'ops': [['reject', 5], ['ins', 'L1', 'e0'], ['ins', 'L2', None]], 'text': 'nxmy'} | Passed |
| typing into an empty document | {'ops': [['ins', 'L1', None], ['ins', 'L2', 'L1'], ['ins', 'L3', 'L2']], 'text': 'hi!'} | {'ops': [['ins', 'L1', None], ['ins', 'L2', 'L1'], ['ins', 'L3', 'L2']], 'text': 'hi!'} | Passed |
| mixed edits | {'ops': [['del', 'e2'], ['ins', 'L1', 'e0'], ['ins', 'L2', 'e4']], 'text': 'hElo?'} | {'ops': [['del', 'e2'], ['ins', 'L1', 'e0'], ['ins', 'L2', 'e4']], 'text': 'hElo?'} | Passed |
SHA-256 / f442879e70a927fc6310e255f5ae0a30a1772555903470c8f30318698b00183e
Verification & scope
A deterministic, bounded teaching model of one replicated data type with stipulated operation and merge rules; it is not a production CRDT library and makes no claim of conformance to any specific published design. This reproducer isolates one failure mechanism. Results cover the supplied fixtures. Variants within a family share a test contract and should remain grouped when constructing evaluation splits. Related mechanisms with a shared evaluation_group must also remain together; these controlled models are not independent production incidents.
Observations recorded using Python 3.12.14 at 2026-09-29T14:49:03.694406+00:00.
Case digest / 1cc95d4cc2540750c3e378a0dc528cf3b9901f1848639d182a53e5ec4871fdaf