broken_source:
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(base, ours, theirs):
    MISSING = object()
    merged, conflicts = {}, []
    for k in sorted(set(base) | set(ours)):
        b = base.get(k, MISSING)
        o = ours.get(k, MISSING)
        t = theirs.get(k, MISSING)
        if o == t:
            r = o
        elif o == b:
            r = t
        elif t == b:
            r = o
        else:
            conflicts.append(k)
            r = o
        if r is not MISSING:
            merged[k] = r
    return {'merged': sorted([k, v] for k, v in merged.items()), 'conflicts': conflicts}
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
cases = {
    1: [('each side changes a different key', [{'host': 'a', 'port': '80', 'mode': 'x'}, {'host': 'b', 'port': '80', 'mode': 'x'}, {'host': 'a', 'port': '81', 'mode': 'x'}], {'merged': [['host', 'b'], ['mode', 'x'], ['port', '81']], 'conflicts': []}), ('both change a key the same way', [{'host': 'a', 'port': '80', 'mode': 'x'}, {'host': 'a', 'port': '80', 'mode': 'y'}, {'host': 'a', 'port': '80', 'mode': 'y'}], {'merged': [['host', 'a'], ['mode', 'y'], ['port', '80']], 'conflicts': []}), ('both delete the same key', [{'host': 'a', 'port': '80', 'mode': 'x'}, {'host': 'a', 'port': '80'}, {'host': 'a', 'port': '80'}], {'merged': [['host', 'a'], ['port', '80']], 'conflicts': []}), ('conflicting changes keep ours', [{'host': 'a', 'port': '80', 'mode': 'x'}, {'host': 'a', 'port': '1', 'mode': 'x'}, {'host': 'a', 'port': '2', 'mode': 'x'}], {'merged': [['host', 'a'], ['mode', 'x'], ['port', '1']], 'conflicts': ['port']}), ('delete versus modify conflicts', [{'host': 'a', 'port': '80', 'mode': 'x'}, {'host': 'a', 'port': '80', 'mode': 'z1'}, {'host': 'a', 'port': '80'}], {'merged': [['host', 'a'], ['mode', 'z1'], ['port', '80']], 'conflicts': ['mode']}), ('explicit null differs from deletion', [{'host': 'a', 'port': '80', 'mode': 'x'}, {'host': 'a', 'port': '80', 'mode': None}, {'host': 'a', 'port': '80', 'mode': 'x'}], {'merged': [['host', 'a'], ['mode', None], ['port', '80']], 'conflicts': []}), ('key added only by theirs', [{'host': 'a', 'port': '80', 'mode': 'x'}, {'host': 'a', 'port': '80', 'mode': 'x'}, {'host': 'a', 'port': '80', 'mode': 'x', 'extra': 'e1'}], {'merged': [['extra', 'e1'], ['host', 'a'], ['mode', 'x'], ['port', '80']], 'conflicts': []}), ('key added only by ours', [{'host': 'a', 'port': '80', 'mode': 'x'}, {'host': 'a', 'port': '80', 'mode': 'x', 'mine': 'm1'}, {'host': 'a', 'port': '80', 'mode': 'x'}], {'merged': [['host', 'a'], ['mine', 'm1'], ['mode', 'x'], ['port', '80']], 'conflicts': []}), ('modify versus delete conflicts', [{'host': 'a', 'port': '80', 'mode': 'x'}, {'host': 'a', 'mode': 'x'}, {'host': 'a', 'port': '443', 'mode': 'x'}], {'merged': [['host', 'a'], ['mode', 'x']], 'conflicts': ['port']}), ('null in base and deleted by ours', [{'k': None, 'j': '1'}, {'j': '1'}, {'k': None, 'j': '2'}], {'merged': [['j', '2']], 'conflicts': []})],
    2: [('each side changes a different key', [{'host': 'a', 'port': '80', 'mode': 'x'}, {'host': 'b', 'port': '80', 'mode': 'x'}, {'host': 'a', 'port': '82', 'mode': 'x'}], {'merged': [['host', 'b'], ['mode', 'x'], ['port', '82']], 'conflicts': []}), ('both change a key the same way', [{'host': 'a', 'port': '80', 'mode': 'x'}, {'host': 'a', 'port': '80', 'mode': 'y'}, {'host': 'a', 'port': '80', 'mode': 'y'}], {'merged': [['host', 'a'], ['mode', 'y'], ['port', '80']], 'conflicts': []}), ('both delete the same key', [{'host': 'a', 'port': '80', 'mode': 'x'}, {'host': 'a', 'port': '80'}, {'host': 'a', 'port': '80'}], {'merged': [['host', 'a'], ['port', '80']], 'conflicts': []}), ('conflicting changes keep ours', [{'host': 'a', 'port': '80', 'mode': 'x'}, {'host': 'a', 'port': '1', 'mode': 'x'}, {'host': 'a', 'port': '2', 'mode': 'x'}], {'merged': [['host', 'a'], ['mode', 'x'], ['port', '1']], 'conflicts': ['port']}), ('delete versus modify conflicts', [{'host': 'a', 'port': '80', 'mode': 'x'}, {'host': 'a', 'port': '80', 'mode': 'z2'}, {'host': 'a', 'port': '80'}], {'merged': [['host', 'a'], ['mode', 'z2'], ['port', '80']], 'conflicts': ['mode']}), ('explicit null differs from deletion', [{'host': 'a', 'port': '80', 'mode': 'x'}, {'host': 'a', 'port': '80', 'mode': None}, {'host': 'a', 'port': '80', 'mode': 'x'}], {'merged': [['host', 'a'], ['mode', None], ['port', '80']], 'conflicts': []}), ('key added only by theirs', [{'host': 'a', 'port': '80', 'mode': 'x'}, {'host': 'a', 'port': '80', 'mode': 'x'}, {'host': 'a', 'port': '80', 'mode': 'x', 'extra': 'e2'}], {'merged': [['extra', 'e2'], ['host', 'a'], ['mode', 'x'], ['port', '80']], 'conflicts': []}), ('key added only by ours', [{'host': 'a', 'port': '80', 'mode': 'x'}, {'host': 'a', 'port': '80', 'mode': 'x', 'mine': 'm2'}, {'host': 'a', 'port': '80', 'mode': 'x'}], {'merged': [['host', 'a'], ['mine', 'm2'], ['mode', 'x'], ['port', '80']], 'conflicts': []}), ('modify versus delete conflicts', [{'host': 'a', 'port': '80', 'mode': 'x'}, {'host': 'a', 'mode': 'x'}, {'host': 'a', 'port': '443', 'mode': 'x'}], {'merged': [['host', 'a'], ['mode', 'x']], 'conflicts': ['port']}), ('null in base and deleted by ours', [{'k': None, 'j': '1'}, {'j': '1'}, {'k': None, 'j': '2'}], {'merged': [['j', '2']], 'conflicts': []})],
    3: [('each side changes a different key', [{'host': 'a', 'port': '80', 'mode': 'x'}, {'host': 'b', 'port': '80', 'mode': 'x'}, {'host': 'a', 'port': '83', 'mode': 'x'}], {'merged': [['host', 'b'], ['mode', 'x'], ['port', '83']], 'conflicts': []}), ('both change a key the same way', [{'host': 'a', 'port': '80', 'mode': 'x'}, {'host': 'a', 'port': '80', 'mode': 'y'}, {'host': 'a', 'port': '80', 'mode': 'y'}], {'merged': [['host', 'a'], ['mode', 'y'], ['port', '80']], 'conflicts': []}), ('both delete the same key', [{'host': 'a', 'port': '80', 'mode': 'x'}, {'host': 'a', 'port': '80'}, {'host': 'a', 'port': '80'}], {'merged': [['host', 'a'], ['port', '80']], 'conflicts': []}), ('conflicting changes keep ours', [{'host': 'a', 'port': '80', 'mode': 'x'}, {'host': 'a', 'port': '1', 'mode': 'x'}, {'host': 'a', 'port': '2', 'mode': 'x'}], {'merged': [['host', 'a'], ['mode', 'x'], ['port', '1']], 'conflicts': ['port']}), ('delete versus modify conflicts', [{'host': 'a', 'port': '80', 'mode': 'x'}, {'host': 'a', 'port': '80', 'mode': 'z3'}, {'host': 'a', 'port': '80'}], {'merged': [['host', 'a'], ['mode', 'z3'], ['port', '80']], 'conflicts': ['mode']}), ('explicit null differs from deletion', [{'host': 'a', 'port': '80', 'mode': 'x'}, {'host': 'a', 'port': '80', 'mode': None}, {'host': 'a', 'port': '80', 'mode': 'x'}], {'merged': [['host', 'a'], ['mode', None], ['port', '80']], 'conflicts': []}), ('key added only by theirs', [{'host': 'a', 'port': '80', 'mode': 'x'}, {'host': 'a', 'port': '80', 'mode': 'x'}, {'host': 'a', 'port': '80', 'mode': 'x', 'extra': 'e3'}], {'merged': [['extra', 'e3'], ['host', 'a'], ['mode', 'x'], ['port', '80']], 'conflicts': []}), ('key added only by ours', [{'host': 'a', 'port': '80', 'mode': 'x'}, {'host': 'a', 'port': '80', 'mode': 'x', 'mine': 'm3'}, {'host': 'a', 'port': '80', 'mode': 'x'}], {'merged': [['host', 'a'], ['mine', 'm3'], ['mode', 'x'], ['port', '80']], 'conflicts': []}), ('modify versus delete conflicts', [{'host': 'a', 'port': '80', 'mode': 'x'}, {'host': 'a', 'mode': 'x'}, {'host': 'a', 'port': '443', 'mode': 'x'}], {'merged': [['host', 'a'], ['mode', 'x']], 'conflicts': ['port']}), ('null in base and deleted by ours', [{'k': None, 'j': '1'}, {'j': '1'}, {'k': None, 'j': '2'}], {'merged': [['j', '2']], 'conflicts': []})],
    4: [('each side changes a different key', [{'host': 'a', 'port': '80', 'mode': 'x'}, {'host': 'b', 'port': '80', 'mode': 'x'}, {'host': 'a', 'port': '84', 'mode': 'x'}], {'merged': [['host', 'b'], ['mode', 'x'], ['port', '84']], 'conflicts': []}), ('both change a key the same way', [{'host': 'a', 'port': '80', 'mode': 'x'}, {'host': 'a', 'port': '80', 'mode': 'y'}, {'host': 'a', 'port': '80', 'mode': 'y'}], {'merged': [['host', 'a'], ['mode', 'y'], ['port', '80']], 'conflicts': []}), ('both delete the same key', [{'host': 'a', 'port': '80', 'mode': 'x'}, {'host': 'a', 'port': '80'}, {'host': 'a', 'port': '80'}], {'merged': [['host', 'a'], ['port', '80']], 'conflicts': []}), ('conflicting changes keep ours', [{'host': 'a', 'port': '80', 'mode': 'x'}, {'host': 'a', 'port': '1', 'mode': 'x'}, {'host': 'a', 'port': '2', 'mode': 'x'}], {'merged': [['host', 'a'], ['mode', 'x'], ['port', '1']], 'conflicts': ['port']}), ('delete versus modify conflicts', [{'host': 'a', 'port': '80', 'mode': 'x'}, {'host': 'a', 'port': '80', 'mode': 'z4'}, {'host': 'a', 'port': '80'}], {'merged': [['host', 'a'], ['mode', 'z4'], ['port', '80']], 'conflicts': ['mode']}), ('explicit null differs from deletion', [{'host': 'a', 'port': '80', 'mode': 'x'}, {'host': 'a', 'port': '80', 'mode': None}, {'host': 'a', 'port': '80', 'mode': 'x'}], {'merged': [['host', 'a'], ['mode', None], ['port', '80']], 'conflicts': []}), ('key added only by theirs', [{'host': 'a', 'port': '80', 'mode': 'x'}, {'host': 'a', 'port': '80', 'mode': 'x'}, {'host': 'a', 'port': '80', 'mode': 'x', 'extra': 'e4'}], {'merged': [['extra', 'e4'], ['host', 'a'], ['mode', 'x'], ['port', '80']], 'conflicts': []}), ('key added only by ours', [{'host': 'a', 'port': '80', 'mode': 'x'}, {'host': 'a', 'port': '80', 'mode': 'x', 'mine': 'm4'}, {'host': 'a', 'port': '80', 'mode': 'x'}], {'merged': [['host', 'a'], ['mine', 'm4'], ['mode', 'x'], ['port', '80']], 'conflicts': []}), ('modify versus delete conflicts', [{'host': 'a', 'port': '80', 'mode': 'x'}, {'host': 'a', 'mode': 'x'}, {'host': 'a', 'port': '443', 'mode': 'x'}], {'merged': [['host', 'a'], ['mode', 'x']], 'conflicts': ['port']}), ('null in base and deleted by ours', [{'k': None, 'j': '1'}, {'j': '1'}, {'k': None, 'j': '2'}], {'merged': [['j', '2']], 'conflicts': []})],
    5: [('each side changes a different key', [{'host': 'a', 'port': '80', 'mode': 'x'}, {'host': 'b', 'port': '80', 'mode': 'x'}, {'host': 'a', 'port': '85', 'mode': 'x'}], {'merged': [['host', 'b'], ['mode', 'x'], ['port', '85']], 'conflicts': []}), ('both change a key the same way', [{'host': 'a', 'port': '80', 'mode': 'x'}, {'host': 'a', 'port': '80', 'mode': 'y'}, {'host': 'a', 'port': '80', 'mode': 'y'}], {'merged': [['host', 'a'], ['mode', 'y'], ['port', '80']], 'conflicts': []}), ('both delete the same key', [{'host': 'a', 'port': '80', 'mode': 'x'}, {'host': 'a', 'port': '80'}, {'host': 'a', 'port': '80'}], {'merged': [['host', 'a'], ['port', '80']], 'conflicts': []}), ('conflicting changes keep ours', [{'host': 'a', 'port': '80', 'mode': 'x'}, {'host': 'a', 'port': '1', 'mode': 'x'}, {'host': 'a', 'port': '2', 'mode': 'x'}], {'merged': [['host', 'a'], ['mode', 'x'], ['port', '1']], 'conflicts': ['port']}), ('delete versus modify conflicts', [{'host': 'a', 'port': '80', 'mode': 'x'}, {'host': 'a', 'port': '80', 'mode': 'z5'}, {'host': 'a', 'port': '80'}], {'merged': [['host', 'a'], ['mode', 'z5'], ['port', '80']], 'conflicts': ['mode']}), ('explicit null differs from deletion', [{'host': 'a', 'port': '80', 'mode': 'x'}, {'host': 'a', 'port': '80', 'mode': None}, {'host': 'a', 'port': '80', 'mode': 'x'}], {'merged': [['host', 'a'], ['mode', None], ['port', '80']], 'conflicts': []}), ('key added only by theirs', [{'host': 'a', 'port': '80', 'mode': 'x'}, {'host': 'a', 'port': '80', 'mode': 'x'}, {'host': 'a', 'port': '80', 'mode': 'x', 'extra': 'e5'}], {'merged': [['extra', 'e5'], ['host', 'a'], ['mode', 'x'], ['port', '80']], 'conflicts': []}), ('key added only by ours', [{'host': 'a', 'port': '80', 'mode': 'x'}, {'host': 'a', 'port': '80', 'mode': 'x', 'mine': 'm5'}, {'host': 'a', 'port': '80', 'mode': 'x'}], {'merged': [['host', 'a'], ['mine', 'm5'], ['mode', 'x'], ['port', '80']], 'conflicts': []}), ('modify versus delete conflicts', [{'host': 'a', 'port': '80', 'mode': 'x'}, {'host': 'a', 'mode': 'x'}, {'host': 'a', 'port': '443', 'mode': 'x'}], {'merged': [['host', 'a'], ['mode', 'x']], 'conflicts': ['port']}), ('null in base and deleted by ours', [{'k': None, 'j': '1'}, {'j': '1'}, {'k': None, 'j': '2'}], {'merged': [['j', '2']], 'conflicts': []})],
}[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)

source:
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(base, ours, theirs):
    MISSING = object()
    merged, conflicts = {}, []
    for k in sorted(set(base) | set(theirs)):
        b = base.get(k, MISSING)
        o = ours.get(k, MISSING)
        t = theirs.get(k, MISSING)
        if o == t:
            r = o
        elif o == b:
            r = t
        elif t == b:
            r = o
        else:
            conflicts.append(k)
            r = o
        if r is not MISSING:
            merged[k] = r
    return {'merged': sorted([k, v] for k, v in merged.items()), 'conflicts': conflicts}
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
cases = {
    1: [('each side changes a different key', [{'host': 'a', 'port': '80', 'mode': 'x'}, {'host': 'b', 'port': '80', 'mode': 'x'}, {'host': 'a', 'port': '81', 'mode': 'x'}], {'merged': [['host', 'b'], ['mode', 'x'], ['port', '81']], 'conflicts': []}), ('both change a key the same way', [{'host': 'a', 'port': '80', 'mode': 'x'}, {'host': 'a', 'port': '80', 'mode': 'y'}, {'host': 'a', 'port': '80', 'mode': 'y'}], {'merged': [['host', 'a'], ['mode', 'y'], ['port', '80']], 'conflicts': []}), ('both delete the same key', [{'host': 'a', 'port': '80', 'mode': 'x'}, {'host': 'a', 'port': '80'}, {'host': 'a', 'port': '80'}], {'merged': [['host', 'a'], ['port', '80']], 'conflicts': []}), ('conflicting changes keep ours', [{'host': 'a', 'port': '80', 'mode': 'x'}, {'host': 'a', 'port': '1', 'mode': 'x'}, {'host': 'a', 'port': '2', 'mode': 'x'}], {'merged': [['host', 'a'], ['mode', 'x'], ['port', '1']], 'conflicts': ['port']}), ('delete versus modify conflicts', [{'host': 'a', 'port': '80', 'mode': 'x'}, {'host': 'a', 'port': '80', 'mode': 'z1'}, {'host': 'a', 'port': '80'}], {'merged': [['host', 'a'], ['mode', 'z1'], ['port', '80']], 'conflicts': ['mode']}), ('explicit null differs from deletion', [{'host': 'a', 'port': '80', 'mode': 'x'}, {'host': 'a', 'port': '80', 'mode': None}, {'host': 'a', 'port': '80', 'mode': 'x'}], {'merged': [['host', 'a'], ['mode', None], ['port', '80']], 'conflicts': []}), ('key added only by theirs', [{'host': 'a', 'port': '80', 'mode': 'x'}, {'host': 'a', 'port': '80', 'mode': 'x'}, {'host': 'a', 'port': '80', 'mode': 'x', 'extra': 'e1'}], {'merged': [['extra', 'e1'], ['host', 'a'], ['mode', 'x'], ['port', '80']], 'conflicts': []}), ('key added only by ours', [{'host': 'a', 'port': '80', 'mode': 'x'}, {'host': 'a', 'port': '80', 'mode': 'x', 'mine': 'm1'}, {'host': 'a', 'port': '80', 'mode': 'x'}], {'merged': [['host', 'a'], ['mine', 'm1'], ['mode', 'x'], ['port', '80']], 'conflicts': []}), ('modify versus delete conflicts', [{'host': 'a', 'port': '80', 'mode': 'x'}, {'host': 'a', 'mode': 'x'}, {'host': 'a', 'port': '443', 'mode': 'x'}], {'merged': [['host', 'a'], ['mode', 'x']], 'conflicts': ['port']}), ('null in base and deleted by ours', [{'k': None, 'j': '1'}, {'j': '1'}, {'k': None, 'j': '2'}], {'merged': [['j', '2']], 'conflicts': []})],
    2: [('each side changes a different key', [{'host': 'a', 'port': '80', 'mode': 'x'}, {'host': 'b', 'port': '80', 'mode': 'x'}, {'host': 'a', 'port': '82', 'mode': 'x'}], {'merged': [['host', 'b'], ['mode', 'x'], ['port', '82']], 'conflicts': []}), ('both change a key the same way', [{'host': 'a', 'port': '80', 'mode': 'x'}, {'host': 'a', 'port': '80', 'mode': 'y'}, {'host': 'a', 'port': '80', 'mode': 'y'}], {'merged': [['host', 'a'], ['mode', 'y'], ['port', '80']], 'conflicts': []}), ('both delete the same key', [{'host': 'a', 'port': '80', 'mode': 'x'}, {'host': 'a', 'port': '80'}, {'host': 'a', 'port': '80'}], {'merged': [['host', 'a'], ['port', '80']], 'conflicts': []}), ('conflicting changes keep ours', [{'host': 'a', 'port': '80', 'mode': 'x'}, {'host': 'a', 'port': '1', 'mode': 'x'}, {'host': 'a', 'port': '2', 'mode': 'x'}], {'merged': [['host', 'a'], ['mode', 'x'], ['port', '1']], 'conflicts': ['port']}), ('delete versus modify conflicts', [{'host': 'a', 'port': '80', 'mode': 'x'}, {'host': 'a', 'port': '80', 'mode': 'z2'}, {'host': 'a', 'port': '80'}], {'merged': [['host', 'a'], ['mode', 'z2'], ['port', '80']], 'conflicts': ['mode']}), ('explicit null differs from deletion', [{'host': 'a', 'port': '80', 'mode': 'x'}, {'host': 'a', 'port': '80', 'mode': None}, {'host': 'a', 'port': '80', 'mode': 'x'}], {'merged': [['host', 'a'], ['mode', None], ['port', '80']], 'conflicts': []}), ('key added only by theirs', [{'host': 'a', 'port': '80', 'mode': 'x'}, {'host': 'a', 'port': '80', 'mode': 'x'}, {'host': 'a', 'port': '80', 'mode': 'x', 'extra': 'e2'}], {'merged': [['extra', 'e2'], ['host', 'a'], ['mode', 'x'], ['port', '80']], 'conflicts': []}), ('key added only by ours', [{'host': 'a', 'port': '80', 'mode': 'x'}, {'host': 'a', 'port': '80', 'mode': 'x', 'mine': 'm2'}, {'host': 'a', 'port': '80', 'mode': 'x'}], {'merged': [['host', 'a'], ['mine', 'm2'], ['mode', 'x'], ['port', '80']], 'conflicts': []}), ('modify versus delete conflicts', [{'host': 'a', 'port': '80', 'mode': 'x'}, {'host': 'a', 'mode': 'x'}, {'host': 'a', 'port': '443', 'mode': 'x'}], {'merged': [['host', 'a'], ['mode', 'x']], 'conflicts': ['port']}), ('null in base and deleted by ours', [{'k': None, 'j': '1'}, {'j': '1'}, {'k': None, 'j': '2'}], {'merged': [['j', '2']], 'conflicts': []})],
    3: [('each side changes a different key', [{'host': 'a', 'port': '80', 'mode': 'x'}, {'host': 'b', 'port': '80', 'mode': 'x'}, {'host': 'a', 'port': '83', 'mode': 'x'}], {'merged': [['host', 'b'], ['mode', 'x'], ['port', '83']], 'conflicts': []}), ('both change a key the same way', [{'host': 'a', 'port': '80', 'mode': 'x'}, {'host': 'a', 'port': '80', 'mode': 'y'}, {'host': 'a', 'port': '80', 'mode': 'y'}], {'merged': [['host', 'a'], ['mode', 'y'], ['port', '80']], 'conflicts': []}), ('both delete the same key', [{'host': 'a', 'port': '80', 'mode': 'x'}, {'host': 'a', 'port': '80'}, {'host': 'a', 'port': '80'}], {'merged': [['host', 'a'], ['port', '80']], 'conflicts': []}), ('conflicting changes keep ours', [{'host': 'a', 'port': '80', 'mode': 'x'}, {'host': 'a', 'port': '1', 'mode': 'x'}, {'host': 'a', 'port': '2', 'mode': 'x'}], {'merged': [['host', 'a'], ['mode', 'x'], ['port', '1']], 'conflicts': ['port']}), ('delete versus modify conflicts', [{'host': 'a', 'port': '80', 'mode': 'x'}, {'host': 'a', 'port': '80', 'mode': 'z3'}, {'host': 'a', 'port': '80'}], {'merged': [['host', 'a'], ['mode', 'z3'], ['port', '80']], 'conflicts': ['mode']}), ('explicit null differs from deletion', [{'host': 'a', 'port': '80', 'mode': 'x'}, {'host': 'a', 'port': '80', 'mode': None}, {'host': 'a', 'port': '80', 'mode': 'x'}], {'merged': [['host', 'a'], ['mode', None], ['port', '80']], 'conflicts': []}), ('key added only by theirs', [{'host': 'a', 'port': '80', 'mode': 'x'}, {'host': 'a', 'port': '80', 'mode': 'x'}, {'host': 'a', 'port': '80', 'mode': 'x', 'extra': 'e3'}], {'merged': [['extra', 'e3'], ['host', 'a'], ['mode', 'x'], ['port', '80']], 'conflicts': []}), ('key added only by ours', [{'host': 'a', 'port': '80', 'mode': 'x'}, {'host': 'a', 'port': '80', 'mode': 'x', 'mine': 'm3'}, {'host': 'a', 'port': '80', 'mode': 'x'}], {'merged': [['host', 'a'], ['mine', 'm3'], ['mode', 'x'], ['port', '80']], 'conflicts': []}), ('modify versus delete conflicts', [{'host': 'a', 'port': '80', 'mode': 'x'}, {'host': 'a', 'mode': 'x'}, {'host': 'a', 'port': '443', 'mode': 'x'}], {'merged': [['host', 'a'], ['mode', 'x']], 'conflicts': ['port']}), ('null in base and deleted by ours', [{'k': None, 'j': '1'}, {'j': '1'}, {'k': None, 'j': '2'}], {'merged': [['j', '2']], 'conflicts': []})],
    4: [('each side changes a different key', [{'host': 'a', 'port': '80', 'mode': 'x'}, {'host': 'b', 'port': '80', 'mode': 'x'}, {'host': 'a', 'port': '84', 'mode': 'x'}], {'merged': [['host', 'b'], ['mode', 'x'], ['port', '84']], 'conflicts': []}), ('both change a key the same way', [{'host': 'a', 'port': '80', 'mode': 'x'}, {'host': 'a', 'port': '80', 'mode': 'y'}, {'host': 'a', 'port': '80', 'mode': 'y'}], {'merged': [['host', 'a'], ['mode', 'y'], ['port', '80']], 'conflicts': []}), ('both delete the same key', [{'host': 'a', 'port': '80', 'mode': 'x'}, {'host': 'a', 'port': '80'}, {'host': 'a', 'port': '80'}], {'merged': [['host', 'a'], ['port', '80']], 'conflicts': []}), ('conflicting changes keep ours', [{'host': 'a', 'port': '80', 'mode': 'x'}, {'host': 'a', 'port': '1', 'mode': 'x'}, {'host': 'a', 'port': '2', 'mode': 'x'}], {'merged': [['host', 'a'], ['mode', 'x'], ['port', '1']], 'conflicts': ['port']}), ('delete versus modify conflicts', [{'host': 'a', 'port': '80', 'mode': 'x'}, {'host': 'a', 'port': '80', 'mode': 'z4'}, {'host': 'a', 'port': '80'}], {'merged': [['host', 'a'], ['mode', 'z4'], ['port', '80']], 'conflicts': ['mode']}), ('explicit null differs from deletion', [{'host': 'a', 'port': '80', 'mode': 'x'}, {'host': 'a', 'port': '80', 'mode': None}, {'host': 'a', 'port': '80', 'mode': 'x'}], {'merged': [['host', 'a'], ['mode', None], ['port', '80']], 'conflicts': []}), ('key added only by theirs', [{'host': 'a', 'port': '80', 'mode': 'x'}, {'host': 'a', 'port': '80', 'mode': 'x'}, {'host': 'a', 'port': '80', 'mode': 'x', 'extra': 'e4'}], {'merged': [['extra', 'e4'], ['host', 'a'], ['mode', 'x'], ['port', '80']], 'conflicts': []}), ('key added only by ours', [{'host': 'a', 'port': '80', 'mode': 'x'}, {'host': 'a', 'port': '80', 'mode': 'x', 'mine': 'm4'}, {'host': 'a', 'port': '80', 'mode': 'x'}], {'merged': [['host', 'a'], ['mine', 'm4'], ['mode', 'x'], ['port', '80']], 'conflicts': []}), ('modify versus delete conflicts', [{'host': 'a', 'port': '80', 'mode': 'x'}, {'host': 'a', 'mode': 'x'}, {'host': 'a', 'port': '443', 'mode': 'x'}], {'merged': [['host', 'a'], ['mode', 'x']], 'conflicts': ['port']}), ('null in base and deleted by ours', [{'k': None, 'j': '1'}, {'j': '1'}, {'k': None, 'j': '2'}], {'merged': [['j', '2']], 'conflicts': []})],
    5: [('each side changes a different key', [{'host': 'a', 'port': '80', 'mode': 'x'}, {'host': 'b', 'port': '80', 'mode': 'x'}, {'host': 'a', 'port': '85', 'mode': 'x'}], {'merged': [['host', 'b'], ['mode', 'x'], ['port', '85']], 'conflicts': []}), ('both change a key the same way', [{'host': 'a', 'port': '80', 'mode': 'x'}, {'host': 'a', 'port': '80', 'mode': 'y'}, {'host': 'a', 'port': '80', 'mode': 'y'}], {'merged': [['host', 'a'], ['mode', 'y'], ['port', '80']], 'conflicts': []}), ('both delete the same key', [{'host': 'a', 'port': '80', 'mode': 'x'}, {'host': 'a', 'port': '80'}, {'host': 'a', 'port': '80'}], {'merged': [['host', 'a'], ['port', '80']], 'conflicts': []}), ('conflicting changes keep ours', [{'host': 'a', 'port': '80', 'mode': 'x'}, {'host': 'a', 'port': '1', 'mode': 'x'}, {'host': 'a', 'port': '2', 'mode': 'x'}], {'merged': [['host', 'a'], ['mode', 'x'], ['port', '1']], 'conflicts': ['port']}), ('delete versus modify conflicts', [{'host': 'a', 'port': '80', 'mode': 'x'}, {'host': 'a', 'port': '80', 'mode': 'z5'}, {'host': 'a', 'port': '80'}], {'merged': [['host', 'a'], ['mode', 'z5'], ['port', '80']], 'conflicts': ['mode']}), ('explicit null differs from deletion', [{'host': 'a', 'port': '80', 'mode': 'x'}, {'host': 'a', 'port': '80', 'mode': None}, {'host': 'a', 'port': '80', 'mode': 'x'}], {'merged': [['host', 'a'], ['mode', None], ['port', '80']], 'conflicts': []}), ('key added only by theirs', [{'host': 'a', 'port': '80', 'mode': 'x'}, {'host': 'a', 'port': '80', 'mode': 'x'}, {'host': 'a', 'port': '80', 'mode': 'x', 'extra': 'e5'}], {'merged': [['extra', 'e5'], ['host', 'a'], ['mode', 'x'], ['port', '80']], 'conflicts': []}), ('key added only by ours', [{'host': 'a', 'port': '80', 'mode': 'x'}, {'host': 'a', 'port': '80', 'mode': 'x', 'mine': 'm5'}, {'host': 'a', 'port': '80', 'mode': 'x'}], {'merged': [['host', 'a'], ['mine', 'm5'], ['mode', 'x'], ['port', '80']], 'conflicts': []}), ('modify versus delete conflicts', [{'host': 'a', 'port': '80', 'mode': 'x'}, {'host': 'a', 'mode': 'x'}, {'host': 'a', 'port': '443', 'mode': 'x'}], {'merged': [['host', 'a'], ['mode', 'x']], 'conflicts': ['port']}), ('null in base and deleted by ours', [{'k': None, 'j': '1'}, {'j': '1'}, {'k': None, 'j': '2'}], {'merged': [['j', '2']], 'conflicts': []})],
}[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)

prompt:
New settings introduced on the other branch are missing after the merge.

Merge base, ours and theirs maps key by key over the union of keys; an absent key and a key holding null are different states. If ours and theirs agree, take that state; else if ours equals base take theirs; else if theirs equals base take ours; otherwise record a conflict and keep ours. Return sorted merged [key, value] pairs and sorted conflicting keys.

split: open-access


broken_source:
"""Failure Map reference implementation. Python standard library only."""
import json
import itertools
N = 1
observations = []
def solve(ops):
    res = []
    i = 0
    while i < len(ops):
        if ops[i][0] != '-':
            i += 1
            continue
        dels = []
        while i < len(ops) and ops[i][0] == '-':
            dels.append(ops[i][1])
            i += 1
        adds = []
        while i < len(ops) and ops[i][0] == '+':
            adds.append(ops[i][1])
            i += 1
        for d, a in zip(dels, adds):
            p = 0
            while p < min(len(d), len(a)) and d[p] == a[p]:
                p += 1
            s = 0
            while s < min(len(d), len(a)) and d[-1 - s] == a[-1 - s]:
                s += 1
            res.append([d, a, p, s])
    return res
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
cases = {
    1: [('simple replacement', [[[' ', 'ctx'], ['-', 'value = 1'], ['+', 'value = 21']]], [['value = 1', 'value = 21', 8, 1]]), ('suffix must not overlap prefix', [[['-', 'aa'], ['+', 'aaa']]], [['aa', 'aaa', 2, 0]]), ('overlap with repeated characters', [[['-', 'abab'], ['+', 'ababab']]], [['abab', 'ababab', 4, 0]]), ('pairs do not cross context', [[['-', 'old'], [' ', 'keep'], ['+', 'new']]], []), ('more deletions than insertions', [[['-', 'x1'], ['-', 'x2'], ['+', 'y1']]], [['x1', 'y1', 0, 1]]), ('more insertions than deletions', [[['-', 'p'], ['+', 'q'], ['+', 'r1']]], [['p', 'q', 0, 0]]), ('pure insertion block', [[['+', 'only'], [' ', 'c'], ['-', 'd'], ['+', 'e']]], [['d', 'e', 0, 0]]), ('two blocks', [[['-', 'foo(a)'], ['+', 'foo(b)'], [' ', 'x'], [' ', 'y'], ['-', 'bar'], ['+', 'baz']]], [['foo(a)', 'foo(b)', 4, 1], ['bar', 'baz', 2, 0]])],
    2: [('simple replacement', [[[' ', 'ctx'], ['-', 'value = 1'], ['+', 'value = 22']]], [['value = 1', 'value = 22', 8, 0]]), ('suffix must not overlap prefix', [[['-', 'aa'], ['+', 'aaa']]], [['aa', 'aaa', 2, 0]]), ('overlap with repeated characters', [[['-', 'abab'], ['+', 'abababab']]], [['abab', 'abababab', 4, 0]]), ('pairs do not cross context', [[['-', 'old'], [' ', 'keep'], ['+', 'new']]], []), ('more deletions than insertions', [[['-', 'x1'], ['-', 'x2'], ['+', 'y1']]], [['x1', 'y1', 0, 1]]), ('more insertions than deletions', [[['-', 'p'], ['+', 'q'], ['+', 'r2']]], [['p', 'q', 0, 0]]), ('pure insertion block', [[['+', 'only'], [' ', 'c'], ['-', 'd'], ['+', 'e']]], [['d', 'e', 0, 0]]), ('two blocks', [[['-', 'foo(a)'], ['+', 'foo(b)'], [' ', 'x'], [' ', 'y'], ['-', 'bar'], ['+', 'baz']]], [['foo(a)', 'foo(b)', 4, 1], ['bar', 'baz', 2, 0]])],
    3: [('simple replacement', [[[' ', 'ctx'], ['-', 'value = 1'], ['+', 'value = 23']]], [['value = 1', 'value = 23', 8, 0]]), ('suffix must not overlap prefix', [[['-', 'aa'], ['+', 'aaa']]], [['aa', 'aaa', 2, 0]]), ('overlap with repeated characters', [[['-', 'abab'], ['+', 'ababababab']]], [['abab', 'ababababab', 4, 0]]), ('pairs do not cross context', [[['-', 'old'], [' ', 'keep'], ['+', 'new']]], []), ('more deletions than insertions', [[['-', 'x1'], ['-', 'x2'], ['+', 'y1']]], [['x1', 'y1', 0, 1]]), ('more insertions than deletions', [[['-', 'p'], ['+', 'q'], ['+', 'r3']]], [['p', 'q', 0, 0]]), ('pure insertion block', [[['+', 'only'], [' ', 'c'], ['-', 'd'], ['+', 'e']]], [['d', 'e', 0, 0]]), ('two blocks', [[['-', 'foo(a)'], ['+', 'foo(b)'], [' ', 'x'], [' ', 'y'], ['-', 'bar'], ['+', 'baz']]], [['foo(a)', 'foo(b)', 4, 1], ['bar', 'baz', 2, 0]])],
    4: [('simple replacement', [[[' ', 'ctx'], ['-', 'value = 1'], ['+', 'value = 24']]], [['value = 1', 'value = 24', 8, 0]]), ('suffix must not overlap prefix', [[['-', 'aa'], ['+', 'aaa']]], [['aa', 'aaa', 2, 0]]), ('overlap with repeated characters', [[['-', 'abab'], ['+', 'abababababab']]], [['abab', 'abababababab', 4, 0]]), ('pairs do not cross context', [[['-', 'old'], [' ', 'keep'], ['+', 'new']]], []), ('more deletions than insertions', [[['-', 'x1'], ['-', 'x2'], ['+', 'y1']]], [['x1', 'y1', 0, 1]]), ('more insertions than deletions', [[['-', 'p'], ['+', 'q'], ['+', 'r4']]], [['p', 'q', 0, 0]]), ('pure insertion block', [[['+', 'only'], [' ', 'c'], ['-', 'd'], ['+', 'e']]], [['d', 'e', 0, 0]]), ('two blocks', [[['-', 'foo(a)'], ['+', 'foo(b)'], [' ', 'x'], [' ', 'y'], ['-', 'bar'], ['+', 'baz']]], [['foo(a)', 'foo(b)', 4, 1], ['bar', 'baz', 2, 0]])],
    5: [('simple replacement', [[[' ', 'ctx'], ['-', 'value = 1'], ['+', 'value = 25']]], [['value = 1', 'value = 25', 8, 0]]), ('suffix must not overlap prefix', [[['-', 'aa'], ['+', 'aaa']]], [['aa', 'aaa', 2, 0]]), ('overlap with repeated characters', [[['-', 'abab'], ['+', 'ababababababab']]], [['abab', 'ababababababab', 4, 0]]), ('pairs do not cross context', [[['-', 'old'], [' ', 'keep'], ['+', 'new']]], []), ('more deletions than insertions', [[['-', 'x1'], ['-', 'x2'], ['+', 'y1']]], [['x1', 'y1', 0, 1]]), ('more insertions than deletions', [[['-', 'p'], ['+', 'q'], ['+', 'r5']]], [['p', 'q', 0, 0]]), ('pure insertion block', [[['+', 'only'], [' ', 'c'], ['-', 'd'], ['+', 'e']]], [['d', 'e', 0, 0]]), ('two blocks', [[['-', 'foo(a)'], ['+', 'foo(b)'], [' ', 'x'], [' ', 'y'], ['-', 'bar'], ['+', 'baz']]], [['foo(a)', 'foo(b)', 4, 1], ['bar', 'baz', 2, 0]])],
}[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)

meaning: Fixture-count band, not measured model difficulty

deps: stdlib

source:
"""Failure Map reference implementation. Python standard library only."""
import json
import itertools
N = 1
observations = []
def solve(ops):
    res = []
    i = 0
    while i < len(ops):
        if ops[i][0] != '-':
            i += 1
            continue
        dels = []
        while i < len(ops) and ops[i][0] == '-':
            dels.append(ops[i][1])
            i += 1
        adds = []
        while i < len(ops) and ops[i][0] == '+':
            adds.append(ops[i][1])
            i += 1
        for d, a in zip(dels, adds):
            p = 0
            while p < min(len(d), len(a)) and d[p] == a[p]:
                p += 1
            s = 0
            while s < max(len(d), len(a)) - p - 1 and s < min(len(d), len(a)) and d[-1 - s] == a[-1 - s]:
                s += 1
            res.append([d, a, p, s])
    return res
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
cases = {
    1: [('simple replacement', [[[' ', 'ctx'], ['-', 'value = 1'], ['+', 'value = 21']]], [['value = 1', 'value = 21', 8, 1]]), ('suffix must not overlap prefix', [[['-', 'aa'], ['+', 'aaa']]], [['aa', 'aaa', 2, 0]]), ('overlap with repeated characters', [[['-', 'abab'], ['+', 'ababab']]], [['abab', 'ababab', 4, 0]]), ('pairs do not cross context', [[['-', 'old'], [' ', 'keep'], ['+', 'new']]], []), ('more deletions than insertions', [[['-', 'x1'], ['-', 'x2'], ['+', 'y1']]], [['x1', 'y1', 0, 1]]), ('more insertions than deletions', [[['-', 'p'], ['+', 'q'], ['+', 'r1']]], [['p', 'q', 0, 0]]), ('pure insertion block', [[['+', 'only'], [' ', 'c'], ['-', 'd'], ['+', 'e']]], [['d', 'e', 0, 0]]), ('two blocks', [[['-', 'foo(a)'], ['+', 'foo(b)'], [' ', 'x'], [' ', 'y'], ['-', 'bar'], ['+', 'baz']]], [['foo(a)', 'foo(b)', 4, 1], ['bar', 'baz', 2, 0]])],
    2: [('simple replacement', [[[' ', 'ctx'], ['-', 'value = 1'], ['+', 'value = 22']]], [['value = 1', 'value = 22', 8, 0]]), ('suffix must not overlap prefix', [[['-', 'aa'], ['+', 'aaa']]], [['aa', 'aaa', 2, 0]]), ('overlap with repeated characters', [[['-', 'abab'], ['+', 'abababab']]], [['abab', 'abababab', 4, 0]]), ('pairs do not cross context', [[['-', 'old'], [' ', 'keep'], ['+', 'new']]], []), ('more deletions than insertions', [[['-', 'x1'], ['-', 'x2'], ['+', 'y1']]], [['x1', 'y1', 0, 1]]), ('more insertions than deletions', [[['-', 'p'], ['+', 'q'], ['+', 'r2']]], [['p', 'q', 0, 0]]), ('pure insertion block', [[['+', 'only'], [' ', 'c'], ['-', 'd'], ['+', 'e']]], [['d', 'e', 0, 0]]), ('two blocks', [[['-', 'foo(a)'], ['+', 'foo(b)'], [' ', 'x'], [' ', 'y'], ['-', 'bar'], ['+', 'baz']]], [['foo(a)', 'foo(b)', 4, 1], ['bar', 'baz', 2, 0]])],
    3: [('simple replacement', [[[' ', 'ctx'], ['-', 'value = 1'], ['+', 'value = 23']]], [['value = 1', 'value = 23', 8, 0]]), ('suffix must not overlap prefix', [[['-', 'aa'], ['+', 'aaa']]], [['aa', 'aaa', 2, 0]]), ('overlap with repeated characters', [[['-', 'abab'], ['+', 'ababababab']]], [['abab', 'ababababab', 4, 0]]), ('pairs do not cross context', [[['-', 'old'], [' ', 'keep'], ['+', 'new']]], []), ('more deletions than insertions', [[['-', 'x1'], ['-', 'x2'], ['+', 'y1']]], [['x1', 'y1', 0, 1]]), ('more insertions than deletions', [[['-', 'p'], ['+', 'q'], ['+', 'r3']]], [['p', 'q', 0, 0]]), ('pure insertion block', [[['+', 'only'], [' ', 'c'], ['-', 'd'], ['+', 'e']]], [['d', 'e', 0, 0]]), ('two blocks', [[['-', 'foo(a)'], ['+', 'foo(b)'], [' ', 'x'], [' ', 'y'], ['-', 'bar'], ['+', 'baz']]], [['foo(a)', 'foo(b)', 4, 1], ['bar', 'baz', 2, 0]])],
    4: [('simple replacement', [[[' ', 'ctx'], ['-', 'value = 1'], ['+', 'value = 24']]], [['value = 1', 'value = 24', 8, 0]]), ('suffix must not overlap prefix', [[['-', 'aa'], ['+', 'aaa']]], [['aa', 'aaa', 2, 0]]), ('overlap with repeated characters', [[['-', 'abab'], ['+', 'abababababab']]], [['abab', 'abababababab', 4, 0]]), ('pairs do not cross context', [[['-', 'old'], [' ', 'keep'], ['+', 'new']]], []), ('more deletions than insertions', [[['-', 'x1'], ['-', 'x2'], ['+', 'y1']]], [['x1', 'y1', 0, 1]]), ('more insertions than deletions', [[['-', 'p'], ['+', 'q'], ['+', 'r4']]], [['p', 'q', 0, 0]]), ('pure insertion block', [[['+', 'only'], [' ', 'c'], ['-', 'd'], ['+', 'e']]], [['d', 'e', 0, 0]]), ('two blocks', [[['-', 'foo(a)'], ['+', 'foo(b)'], [' ', 'x'], [' ', 'y'], ['-', 'bar'], ['+', 'baz']]], [['foo(a)', 'foo(b)', 4, 1], ['bar', 'baz', 2, 0]])],
    5: [('simple replacement', [[[' ', 'ctx'], ['-', 'value = 1'], ['+', 'value = 25']]], [['value = 1', 'value = 25', 8, 0]]), ('suffix must not overlap prefix', [[['-', 'aa'], ['+', 'aaa']]], [['aa', 'aaa', 2, 0]]), ('overlap with repeated characters', [[['-', 'abab'], ['+', 'ababababababab']]], [['abab', 'ababababababab', 4, 0]]), ('pairs do not cross context', [[['-', 'old'], [' ', 'keep'], ['+', 'new']]], []), ('more deletions than insertions', [[['-', 'x1'], ['-', 'x2'], ['+', 'y1']]], [['x1', 'y1', 0, 1]]), ('more insertions than deletions', [[['-', 'p'], ['+', 'q'], ['+', 'r5']]], [['p', 'q', 0, 0]]), ('pure insertion block', [[['+', 'only'], [' ', 'c'], ['-', 'd'], ['+', 'e']]], [['d', 'e', 0, 0]]), ('two blocks', [[['-', 'foo(a)'], ['+', 'foo(b)'], [' ', 'x'], [' ', 'y'], ['-', 'bar'], ['+', 'baz']]], [['foo(a)', 'foo(b)', 4, 1], ['bar', 'baz', 2, 0]])],
}[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)

prompt:
Highlighting marks negative-length changes when one line extends the other.

Within each block of consecutive "-" lines immediately followed by consecutive "+" lines, pair the i-th removed line with the i-th added line (extra lines stay unpaired). For each pair report the common prefix length and the common suffix length, where the suffix may not overlap the prefix. Return [old, new, prefix, suffix] rows.

split: open-access


broken_source:
"""Failure Map reference implementation. Python standard library only."""
import json
import itertools
N = 1
observations = []
def solve(ops):
    res = []
    i = 0
    while i < len(ops):
        if ops[i][0] != '-':
            i += 1
            continue
        dels = []
        while i < len(ops) and ops[i][0] == '-':
            dels.append(ops[i][1])
            i += 1
        while i < len(ops) and ops[i][0] == ' ':
            i += 1
        adds = []
        while i < len(ops) and ops[i][0] == '+':
            adds.append(ops[i][1])
            i += 1
        for d, a in zip(dels, adds):
            p = 0
            while p < min(len(d), len(a)) and d[p] == a[p]:
                p += 1
            s = 0
            while s < min(len(d), len(a)) - p and d[-1 - s] == a[-1 - s]:
                s += 1
            res.append([d, a, p, s])
    return res
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
cases = {
    1: [('simple replacement', [[[' ', 'ctx'], ['-', 'value = 1'], ['+', 'value = 21']]], [['value = 1', 'value = 21', 8, 1]]), ('suffix must not overlap prefix', [[['-', 'aa'], ['+', 'aaa']]], [['aa', 'aaa', 2, 0]]), ('overlap with repeated characters', [[['-', 'abab'], ['+', 'ababab']]], [['abab', 'ababab', 4, 0]]), ('pairs do not cross context', [[['-', 'old'], [' ', 'keep'], ['+', 'new']]], []), ('more deletions than insertions', [[['-', 'x1'], ['-', 'x2'], ['+', 'y1']]], [['x1', 'y1', 0, 1]]), ('more insertions than deletions', [[['-', 'p'], ['+', 'q'], ['+', 'r1']]], [['p', 'q', 0, 0]]), ('pure insertion block', [[['+', 'only'], [' ', 'c'], ['-', 'd'], ['+', 'e']]], [['d', 'e', 0, 0]]), ('two blocks', [[['-', 'foo(a)'], ['+', 'foo(b)'], [' ', 'x'], [' ', 'y'], ['-', 'bar'], ['+', 'baz']]], [['foo(a)', 'foo(b)', 4, 1], ['bar', 'baz', 2, 0]])],
    2: [('simple replacement', [[[' ', 'ctx'], ['-', 'value = 1'], ['+', 'value = 22']]], [['value = 1', 'value = 22', 8, 0]]), ('suffix must not overlap prefix', [[['-', 'aa'], ['+', 'aaa']]], [['aa', 'aaa', 2, 0]]), ('overlap with repeated characters', [[['-', 'abab'], ['+', 'abababab']]], [['abab', 'abababab', 4, 0]]), ('pairs do not cross context', [[['-', 'old'], [' ', 'keep'], ['+', 'new']]], []), ('more deletions than insertions', [[['-', 'x1'], ['-', 'x2'], ['+', 'y1']]], [['x1', 'y1', 0, 1]]), ('more insertions than deletions', [[['-', 'p'], ['+', 'q'], ['+', 'r2']]], [['p', 'q', 0, 0]]), ('pure insertion block', [[['+', 'only'], [' ', 'c'], ['-', 'd'], ['+', 'e']]], [['d', 'e', 0, 0]]), ('two blocks', [[['-', 'foo(a)'], ['+', 'foo(b)'], [' ', 'x'], [' ', 'y'], ['-', 'bar'], ['+', 'baz']]], [['foo(a)', 'foo(b)', 4, 1], ['bar', 'baz', 2, 0]])],
    3: [('simple replacement', [[[' ', 'ctx'], ['-', 'value = 1'], ['+', 'value = 23']]], [['value = 1', 'value = 23', 8, 0]]), ('suffix must not overlap prefix', [[['-', 'aa'], ['+', 'aaa']]], [['aa', 'aaa', 2, 0]]), ('overlap with repeated characters', [[['-', 'abab'], ['+', 'ababababab']]], [['abab', 'ababababab', 4, 0]]), ('pairs do not cross context', [[['-', 'old'], [' ', 'keep'], ['+', 'new']]], []), ('more deletions than insertions', [[['-', 'x1'], ['-', 'x2'], ['+', 'y1']]], [['x1', 'y1', 0, 1]]), ('more insertions than deletions', [[['-', 'p'], ['+', 'q'], ['+', 'r3']]], [['p', 'q', 0, 0]]), ('pure insertion block', [[['+', 'only'], [' ', 'c'], ['-', 'd'], ['+', 'e']]], [['d', 'e', 0, 0]]), ('two blocks', [[['-', 'foo(a)'], ['+', 'foo(b)'], [' ', 'x'], [' ', 'y'], ['-', 'bar'], ['+', 'baz']]], [['foo(a)', 'foo(b)', 4, 1], ['bar', 'baz', 2, 0]])],
    4: [('simple replacement', [[[' ', 'ctx'], ['-', 'value = 1'], ['+', 'value = 24']]], [['value = 1', 'value = 24', 8, 0]]), ('suffix must not overlap prefix', [[['-', 'aa'], ['+', 'aaa']]], [['aa', 'aaa', 2, 0]]), ('overlap with repeated characters', [[['-', 'abab'], ['+', 'abababababab']]], [['abab', 'abababababab', 4, 0]]), ('pairs do not cross context', [[['-', 'old'], [' ', 'keep'], ['+', 'new']]], []), ('more deletions than insertions', [[['-', 'x1'], ['-', 'x2'], ['+', 'y1']]], [['x1', 'y1', 0, 1]]), ('more insertions than deletions', [[['-', 'p'], ['+', 'q'], ['+', 'r4']]], [['p', 'q', 0, 0]]), ('pure insertion block', [[['+', 'only'], [' ', 'c'], ['-', 'd'], ['+', 'e']]], [['d', 'e', 0, 0]]), ('two blocks', [[['-', 'foo(a)'], ['+', 'foo(b)'], [' ', 'x'], [' ', 'y'], ['-', 'bar'], ['+', 'baz']]], [['foo(a)', 'foo(b)', 4, 1], ['bar', 'baz', 2, 0]])],
    5: [('simple replacement', [[[' ', 'ctx'], ['-', 'value = 1'], ['+', 'value = 25']]], [['value = 1', 'value = 25', 8, 0]]), ('suffix must not overlap prefix', [[['-', 'aa'], ['+', 'aaa']]], [['aa', 'aaa', 2, 0]]), ('overlap with repeated characters', [[['-', 'abab'], ['+', 'ababababababab']]], [['abab', 'ababababababab', 4, 0]]), ('pairs do not cross context', [[['-', 'old'], [' ', 'keep'], ['+', 'new']]], []), ('more deletions than insertions', [[['-', 'x1'], ['-', 'x2'], ['+', 'y1']]], [['x1', 'y1', 0, 1]]), ('more insertions than deletions', [[['-', 'p'], ['+', 'q'], ['+', 'r5']]], [['p', 'q', 0, 0]]), ('pure insertion block', [[['+', 'only'], [' ', 'c'], ['-', 'd'], ['+', 'e']]], [['d', 'e', 0, 0]]), ('two blocks', [[['-', 'foo(a)'], ['+', 'foo(b)'], [' ', 'x'], [' ', 'y'], ['-', 'bar'], ['+', 'baz']]], [['foo(a)', 'foo(b)', 4, 1], ['bar', 'baz', 2, 0]])],
}[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)

source:
"""Failure Map reference implementation. Python standard library only."""
import json
import itertools
N = 1
observations = []
def solve(ops):
    res = []
    i = 0
    while i < len(ops):
        if ops[i][0] != '-':
            i += 1
            continue
        dels = []
        while i < len(ops) and ops[i][0] == '-':
            dels.append(ops[i][1])
            i += 1
        if i < len(ops) and ops[i][0] == ' ':
            i += 1
        adds = []
        while i < len(ops) and ops[i][0] == '+':
            adds.append(ops[i][1])
            i += 1
        for d, a in zip(dels, adds):
            p = 0
            while p < min(len(d), len(a)) and d[p] == a[p]:
                p += 1
            s = 0
            while s < min(len(d), len(a)) - p and d[-1 - s] == a[-1 - s]:
                s += 1
            res.append([d, a, p, s])
    return res
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
cases = {
    1: [('simple replacement', [[[' ', 'ctx'], ['-', 'value = 1'], ['+', 'value = 21']]], [['value = 1', 'value = 21', 8, 1]]), ('suffix must not overlap prefix', [[['-', 'aa'], ['+', 'aaa']]], [['aa', 'aaa', 2, 0]]), ('overlap with repeated characters', [[['-', 'abab'], ['+', 'ababab']]], [['abab', 'ababab', 4, 0]]), ('pairs do not cross context', [[['-', 'old'], [' ', 'keep'], ['+', 'new']]], []), ('more deletions than insertions', [[['-', 'x1'], ['-', 'x2'], ['+', 'y1']]], [['x1', 'y1', 0, 1]]), ('more insertions than deletions', [[['-', 'p'], ['+', 'q'], ['+', 'r1']]], [['p', 'q', 0, 0]]), ('pure insertion block', [[['+', 'only'], [' ', 'c'], ['-', 'd'], ['+', 'e']]], [['d', 'e', 0, 0]]), ('two blocks', [[['-', 'foo(a)'], ['+', 'foo(b)'], [' ', 'x'], [' ', 'y'], ['-', 'bar'], ['+', 'baz']]], [['foo(a)', 'foo(b)', 4, 1], ['bar', 'baz', 2, 0]])],
    2: [('simple replacement', [[[' ', 'ctx'], ['-', 'value = 1'], ['+', 'value = 22']]], [['value = 1', 'value = 22', 8, 0]]), ('suffix must not overlap prefix', [[['-', 'aa'], ['+', 'aaa']]], [['aa', 'aaa', 2, 0]]), ('overlap with repeated characters', [[['-', 'abab'], ['+', 'abababab']]], [['abab', 'abababab', 4, 0]]), ('pairs do not cross context', [[['-', 'old'], [' ', 'keep'], ['+', 'new']]], []), ('more deletions than insertions', [[['-', 'x1'], ['-', 'x2'], ['+', 'y1']]], [['x1', 'y1', 0, 1]]), ('more insertions than deletions', [[['-', 'p'], ['+', 'q'], ['+', 'r2']]], [['p', 'q', 0, 0]]), ('pure insertion block', [[['+', 'only'], [' ', 'c'], ['-', 'd'], ['+', 'e']]], [['d', 'e', 0, 0]]), ('two blocks', [[['-', 'foo(a)'], ['+', 'foo(b)'], [' ', 'x'], [' ', 'y'], ['-', 'bar'], ['+', 'baz']]], [['foo(a)', 'foo(b)', 4, 1], ['bar', 'baz', 2, 0]])],
    3: [('simple replacement', [[[' ', 'ctx'], ['-', 'value = 1'], ['+', 'value = 23']]], [['value = 1', 'value = 23', 8, 0]]), ('suffix must not overlap prefix', [[['-', 'aa'], ['+', 'aaa']]], [['aa', 'aaa', 2, 0]]), ('overlap with repeated characters', [[['-', 'abab'], ['+', 'ababababab']]], [['abab', 'ababababab', 4, 0]]), ('pairs do not cross context', [[['-', 'old'], [' ', 'keep'], ['+', 'new']]], []), ('more deletions than insertions', [[['-', 'x1'], ['-', 'x2'], ['+', 'y1']]], [['x1', 'y1', 0, 1]]), ('more insertions than deletions', [[['-', 'p'], ['+', 'q'], ['+', 'r3']]], [['p', 'q', 0, 0]]), ('pure insertion block', [[['+', 'only'], [' ', 'c'], ['-', 'd'], ['+', 'e']]], [['d', 'e', 0, 0]]), ('two blocks', [[['-', 'foo(a)'], ['+', 'foo(b)'], [' ', 'x'], [' ', 'y'], ['-', 'bar'], ['+', 'baz']]], [['foo(a)', 'foo(b)', 4, 1], ['bar', 'baz', 2, 0]])],
    4: [('simple replacement', [[[' ', 'ctx'], ['-', 'value = 1'], ['+', 'value = 24']]], [['value = 1', 'value = 24', 8, 0]]), ('suffix must not overlap prefix', [[['-', 'aa'], ['+', 'aaa']]], [['aa', 'aaa', 2, 0]]), ('overlap with repeated characters', [[['-', 'abab'], ['+', 'abababababab']]], [['abab', 'abababababab', 4, 0]]), ('pairs do not cross context', [[['-', 'old'], [' ', 'keep'], ['+', 'new']]], []), ('more deletions than insertions', [[['-', 'x1'], ['-', 'x2'], ['+', 'y1']]], [['x1', 'y1', 0, 1]]), ('more insertions than deletions', [[['-', 'p'], ['+', 'q'], ['+', 'r4']]], [['p', 'q', 0, 0]]), ('pure insertion block', [[['+', 'only'], [' ', 'c'], ['-', 'd'], ['+', 'e']]], [['d', 'e', 0, 0]]), ('two blocks', [[['-', 'foo(a)'], ['+', 'foo(b)'], [' ', 'x'], [' ', 'y'], ['-', 'bar'], ['+', 'baz']]], [['foo(a)', 'foo(b)', 4, 1], ['bar', 'baz', 2, 0]])],
    5: [('simple replacement', [[[' ', 'ctx'], ['-', 'value = 1'], ['+', 'value = 25']]], [['value = 1', 'value = 25', 8, 0]]), ('suffix must not overlap prefix', [[['-', 'aa'], ['+', 'aaa']]], [['aa', 'aaa', 2, 0]]), ('overlap with repeated characters', [[['-', 'abab'], ['+', 'ababababababab']]], [['abab', 'ababababababab', 4, 0]]), ('pairs do not cross context', [[['-', 'old'], [' ', 'keep'], ['+', 'new']]], []), ('more deletions than insertions', [[['-', 'x1'], ['-', 'x2'], ['+', 'y1']]], [['x1', 'y1', 0, 1]]), ('more insertions than deletions', [[['-', 'p'], ['+', 'q'], ['+', 'r5']]], [['p', 'q', 0, 0]]), ('pure insertion block', [[['+', 'only'], [' ', 'c'], ['-', 'd'], ['+', 'e']]], [['d', 'e', 0, 0]]), ('two blocks', [[['-', 'foo(a)'], ['+', 'foo(b)'], [' ', 'x'], [' ', 'y'], ['-', 'bar'], ['+', 'baz']]], [['foo(a)', 'foo(b)', 4, 1], ['bar', 'baz', 2, 0]])],
}[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)

prompt:
A deletion is highlighted against an unrelated insertion further down.

Within each block of consecutive "-" lines immediately followed by consecutive "+" lines, pair the i-th removed line with the i-th added line (extra lines stay unpaired). For each pair report the common prefix length and the common suffix length, where the suffix may not overlap the prefix. Return [old, new, prefix, suffix] rows.

split: open-access


broken_source:
"""Failure Map reference implementation. Python standard library only."""
import json
import itertools
N = 1
observations = []
def solve(ops):
    res = []
    i = 0
    while i < len(ops):
        if ops[i][0] != '-':
            i += 1
            continue
        dels = []
        while i < len(ops) and ops[i][0] == '-':
            dels.append(ops[i][1])
            i += 1
        adds = []
        while i < len(ops) and ops[i][0] == '+':
            adds.append(ops[i][1])
            i += 1
        for d, a in itertools.zip_longest(dels, adds, fillvalue=''):
            p = 0
            while p < min(len(d), len(a)) and d[p] == a[p]:
                p += 1
            s = 0
            while s < min(len(d), len(a)) - p and d[-1 - s] == a[-1 - s]:
                s += 1
            res.append([d, a, p, s])
    return res
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
cases = {
    1: [('simple replacement', [[[' ', 'ctx'], ['-', 'value = 1'], ['+', 'value = 21']]], [['value = 1', 'value = 21', 8, 1]]), ('suffix must not overlap prefix', [[['-', 'aa'], ['+', 'aaa']]], [['aa', 'aaa', 2, 0]]), ('overlap with repeated characters', [[['-', 'abab'], ['+', 'ababab']]], [['abab', 'ababab', 4, 0]]), ('pairs do not cross context', [[['-', 'old'], [' ', 'keep'], ['+', 'new']]], []), ('more deletions than insertions', [[['-', 'x1'], ['-', 'x2'], ['+', 'y1']]], [['x1', 'y1', 0, 1]]), ('more insertions than deletions', [[['-', 'p'], ['+', 'q'], ['+', 'r1']]], [['p', 'q', 0, 0]]), ('pure insertion block', [[['+', 'only'], [' ', 'c'], ['-', 'd'], ['+', 'e']]], [['d', 'e', 0, 0]]), ('two blocks', [[['-', 'foo(a)'], ['+', 'foo(b)'], [' ', 'x'], [' ', 'y'], ['-', 'bar'], ['+', 'baz']]], [['foo(a)', 'foo(b)', 4, 1], ['bar', 'baz', 2, 0]])],
    2: [('simple replacement', [[[' ', 'ctx'], ['-', 'value = 1'], ['+', 'value = 22']]], [['value = 1', 'value = 22', 8, 0]]), ('suffix must not overlap prefix', [[['-', 'aa'], ['+', 'aaa']]], [['aa', 'aaa', 2, 0]]), ('overlap with repeated characters', [[['-', 'abab'], ['+', 'abababab']]], [['abab', 'abababab', 4, 0]]), ('pairs do not cross context', [[['-', 'old'], [' ', 'keep'], ['+', 'new']]], []), ('more deletions than insertions', [[['-', 'x1'], ['-', 'x2'], ['+', 'y1']]], [['x1', 'y1', 0, 1]]), ('more insertions than deletions', [[['-', 'p'], ['+', 'q'], ['+', 'r2']]], [['p', 'q', 0, 0]]), ('pure insertion block', [[['+', 'only'], [' ', 'c'], ['-', 'd'], ['+', 'e']]], [['d', 'e', 0, 0]]), ('two blocks', [[['-', 'foo(a)'], ['+', 'foo(b)'], [' ', 'x'], [' ', 'y'], ['-', 'bar'], ['+', 'baz']]], [['foo(a)', 'foo(b)', 4, 1], ['bar', 'baz', 2, 0]])],
    3: [('simple replacement', [[[' ', 'ctx'], ['-', 'value = 1'], ['+', 'value = 23']]], [['value = 1', 'value = 23', 8, 0]]), ('suffix must not overlap prefix', [[['-', 'aa'], ['+', 'aaa']]], [['aa', 'aaa', 2, 0]]), ('overlap with repeated characters', [[['-', 'abab'], ['+', 'ababababab']]], [['abab', 'ababababab', 4, 0]]), ('pairs do not cross context', [[['-', 'old'], [' ', 'keep'], ['+', 'new']]], []), ('more deletions than insertions', [[['-', 'x1'], ['-', 'x2'], ['+', 'y1']]], [['x1', 'y1', 0, 1]]), ('more insertions than deletions', [[['-', 'p'], ['+', 'q'], ['+', 'r3']]], [['p', 'q', 0, 0]]), ('pure insertion block', [[['+', 'only'], [' ', 'c'], ['-', 'd'], ['+', 'e']]], [['d', 'e', 0, 0]]), ('two blocks', [[['-', 'foo(a)'], ['+', 'foo(b)'], [' ', 'x'], [' ', 'y'], ['-', 'bar'], ['+', 'baz']]], [['foo(a)', 'foo(b)', 4, 1], ['bar', 'baz', 2, 0]])],
    4: [('simple replacement', [[[' ', 'ctx'], ['-', 'value = 1'], ['+', 'value = 24']]], [['value = 1', 'value = 24', 8, 0]]), ('suffix must not overlap prefix', [[['-', 'aa'], ['+', 'aaa']]], [['aa', 'aaa', 2, 0]]), ('overlap with repeated characters', [[['-', 'abab'], ['+', 'abababababab']]], [['abab', 'abababababab', 4, 0]]), ('pairs do not cross context', [[['-', 'old'], [' ', 'keep'], ['+', 'new']]], []), ('more deletions than insertions', [[['-', 'x1'], ['-', 'x2'], ['+', 'y1']]], [['x1', 'y1', 0, 1]]), ('more insertions than deletions', [[['-', 'p'], ['+', 'q'], ['+', 'r4']]], [['p', 'q', 0, 0]]), ('pure insertion block', [[['+', 'only'], [' ', 'c'], ['-', 'd'], ['+', 'e']]], [['d', 'e', 0, 0]]), ('two blocks', [[['-', 'foo(a)'], ['+', 'foo(b)'], [' ', 'x'], [' ', 'y'], ['-', 'bar'], ['+', 'baz']]], [['foo(a)', 'foo(b)', 4, 1], ['bar', 'baz', 2, 0]])],
    5: [('simple replacement', [[[' ', 'ctx'], ['-', 'value = 1'], ['+', 'value = 25']]], [['value = 1', 'value = 25', 8, 0]]), ('suffix must not overlap prefix', [[['-', 'aa'], ['+', 'aaa']]], [['aa', 'aaa', 2, 0]]), ('overlap with repeated characters', [[['-', 'abab'], ['+', 'ababababababab']]], [['abab', 'ababababababab', 4, 0]]), ('pairs do not cross context', [[['-', 'old'], [' ', 'keep'], ['+', 'new']]], []), ('more deletions than insertions', [[['-', 'x1'], ['-', 'x2'], ['+', 'y1']]], [['x1', 'y1', 0, 1]]), ('more insertions than deletions', [[['-', 'p'], ['+', 'q'], ['+', 'r5']]], [['p', 'q', 0, 0]]), ('pure insertion block', [[['+', 'only'], [' ', 'c'], ['-', 'd'], ['+', 'e']]], [['d', 'e', 0, 0]]), ('two blocks', [[['-', 'foo(a)'], ['+', 'foo(b)'], [' ', 'x'], [' ', 'y'], ['-', 'bar'], ['+', 'baz']]], [['foo(a)', 'foo(b)', 4, 1], ['bar', 'baz', 2, 0]])],
}[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)

source:
"""Failure Map reference implementation. Python standard library only."""
import json
import itertools
N = 1
observations = []
def solve(ops):
    res = []
    i = 0
    while i < len(ops):
        if ops[i][0] != '-':
            i += 1
            continue
        dels = []
        while i < len(ops) and ops[i][0] == '-':
            dels.append(ops[i][1])
            i += 1
        adds = []
        while i < len(ops) and ops[i][0] == '+':
            adds.append(ops[i][1])
            i += 1
        for d, a in [x for x in itertools.zip_longest(dels, adds, fillvalue='') if x[1] != '']:
            p = 0
            while p < min(len(d), len(a)) and d[p] == a[p]:
                p += 1
            s = 0
            while s < min(len(d), len(a)) - p and d[-1 - s] == a[-1 - s]:
                s += 1
            res.append([d, a, p, s])
    return res
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
cases = {
    1: [('simple replacement', [[[' ', 'ctx'], ['-', 'value = 1'], ['+', 'value = 21']]], [['value = 1', 'value = 21', 8, 1]]), ('suffix must not overlap prefix', [[['-', 'aa'], ['+', 'aaa']]], [['aa', 'aaa', 2, 0]]), ('overlap with repeated characters', [[['-', 'abab'], ['+', 'ababab']]], [['abab', 'ababab', 4, 0]]), ('pairs do not cross context', [[['-', 'old'], [' ', 'keep'], ['+', 'new']]], []), ('more deletions than insertions', [[['-', 'x1'], ['-', 'x2'], ['+', 'y1']]], [['x1', 'y1', 0, 1]]), ('more insertions than deletions', [[['-', 'p'], ['+', 'q'], ['+', 'r1']]], [['p', 'q', 0, 0]]), ('pure insertion block', [[['+', 'only'], [' ', 'c'], ['-', 'd'], ['+', 'e']]], [['d', 'e', 0, 0]]), ('two blocks', [[['-', 'foo(a)'], ['+', 'foo(b)'], [' ', 'x'], [' ', 'y'], ['-', 'bar'], ['+', 'baz']]], [['foo(a)', 'foo(b)', 4, 1], ['bar', 'baz', 2, 0]])],
    2: [('simple replacement', [[[' ', 'ctx'], ['-', 'value = 1'], ['+', 'value = 22']]], [['value = 1', 'value = 22', 8, 0]]), ('suffix must not overlap prefix', [[['-', 'aa'], ['+', 'aaa']]], [['aa', 'aaa', 2, 0]]), ('overlap with repeated characters', [[['-', 'abab'], ['+', 'abababab']]], [['abab', 'abababab', 4, 0]]), ('pairs do not cross context', [[['-', 'old'], [' ', 'keep'], ['+', 'new']]], []), ('more deletions than insertions', [[['-', 'x1'], ['-', 'x2'], ['+', 'y1']]], [['x1', 'y1', 0, 1]]), ('more insertions than deletions', [[['-', 'p'], ['+', 'q'], ['+', 'r2']]], [['p', 'q', 0, 0]]), ('pure insertion block', [[['+', 'only'], [' ', 'c'], ['-', 'd'], ['+', 'e']]], [['d', 'e', 0, 0]]), ('two blocks', [[['-', 'foo(a)'], ['+', 'foo(b)'], [' ', 'x'], [' ', 'y'], ['-', 'bar'], ['+', 'baz']]], [['foo(a)', 'foo(b)', 4, 1], ['bar', 'baz', 2, 0]])],
    3: [('simple replacement', [[[' ', 'ctx'], ['-', 'value = 1'], ['+', 'value = 23']]], [['value = 1', 'value = 23', 8, 0]]), ('suffix must not overlap prefix', [[['-', 'aa'], ['+', 'aaa']]], [['aa', 'aaa', 2, 0]]), ('overlap with repeated characters', [[['-', 'abab'], ['+', 'ababababab']]], [['abab', 'ababababab', 4, 0]]), ('pairs do not cross context', [[['-', 'old'], [' ', 'keep'], ['+', 'new']]], []), ('more deletions than insertions', [[['-', 'x1'], ['-', 'x2'], ['+', 'y1']]], [['x1', 'y1', 0, 1]]), ('more insertions than deletions', [[['-', 'p'], ['+', 'q'], ['+', 'r3']]], [['p', 'q', 0, 0]]), ('pure insertion block', [[['+', 'only'], [' ', 'c'], ['-', 'd'], ['+', 'e']]], [['d', 'e', 0, 0]]), ('two blocks', [[['-', 'foo(a)'], ['+', 'foo(b)'], [' ', 'x'], [' ', 'y'], ['-', 'bar'], ['+', 'baz']]], [['foo(a)', 'foo(b)', 4, 1], ['bar', 'baz', 2, 0]])],
    4: [('simple replacement', [[[' ', 'ctx'], ['-', 'value = 1'], ['+', 'value = 24']]], [['value = 1', 'value = 24', 8, 0]]), ('suffix must not overlap prefix', [[['-', 'aa'], ['+', 'aaa']]], [['aa', 'aaa', 2, 0]]), ('overlap with repeated characters', [[['-', 'abab'], ['+', 'abababababab']]], [['abab', 'abababababab', 4, 0]]), ('pairs do not cross context', [[['-', 'old'], [' ', 'keep'], ['+', 'new']]], []), ('more deletions than insertions', [[['-', 'x1'], ['-', 'x2'], ['+', 'y1']]], [['x1', 'y1', 0, 1]]), ('more insertions than deletions', [[['-', 'p'], ['+', 'q'], ['+', 'r4']]], [['p', 'q', 0, 0]]), ('pure insertion block', [[['+', 'only'], [' ', 'c'], ['-', 'd'], ['+', 'e']]], [['d', 'e', 0, 0]]), ('two blocks', [[['-', 'foo(a)'], ['+', 'foo(b)'], [' ', 'x'], [' ', 'y'], ['-', 'bar'], ['+', 'baz']]], [['foo(a)', 'foo(b)', 4, 1], ['bar', 'baz', 2, 0]])],
    5: [('simple replacement', [[[' ', 'ctx'], ['-', 'value = 1'], ['+', 'value = 25']]], [['value = 1', 'value = 25', 8, 0]]), ('suffix must not overlap prefix', [[['-', 'aa'], ['+', 'aaa']]], [['aa', 'aaa', 2, 0]]), ('overlap with repeated characters', [[['-', 'abab'], ['+', 'ababababababab']]], [['abab', 'ababababababab', 4, 0]]), ('pairs do not cross context', [[['-', 'old'], [' ', 'keep'], ['+', 'new']]], []), ('more deletions than insertions', [[['-', 'x1'], ['-', 'x2'], ['+', 'y1']]], [['x1', 'y1', 0, 1]]), ('more insertions than deletions', [[['-', 'p'], ['+', 'q'], ['+', 'r5']]], [['p', 'q', 0, 0]]), ('pure insertion block', [[['+', 'only'], [' ', 'c'], ['-', 'd'], ['+', 'e']]], [['d', 'e', 0, 0]]), ('two blocks', [[['-', 'foo(a)'], ['+', 'foo(b)'], [' ', 'x'], [' ', 'y'], ['-', 'bar'], ['+', 'baz']]], [['foo(a)', 'foo(b)', 4, 1], ['bar', 'baz', 2, 0]])],
}[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)

prompt:
Extra removed or added lines produce spurious pairs against an empty line.

Within each block of consecutive "-" lines immediately followed by consecutive "+" lines, pair the i-th removed line with the i-th added line (extra lines stay unpaired). For each pair report the common prefix length and the common suffix length, where the suffix may not overlap the prefix. Return [old, new, prefix, suffix] rows.

split: open-access


prompt:
Changes to neighbouring lines are auto-merged although the policy treats them as conflicting.

Two patches against the same base list hunks as [old_start, old_len]. A hunk with length > 0 covers lines start..start+len-1; a zero-length hunk is an insertion after line start and sits at start+0.5. Hunks conflict when their spans overlap or are adjacent (within one line). Return sorted [i, j] index pairs of conflicting hunks from the first and second patch.

split: open-access


prompt:
Insertions directly before a changed range are not flagged.

Two patches against the same base list hunks as [old_start, old_len]. A hunk with length > 0 covers lines start..start+len-1; a zero-length hunk is an insertion after line start and sits at start+0.5. Hunks conflict when their spans overlap or are adjacent (within one line). Return sorted [i, j] index pairs of conflicting hunks from the first and second patch.

split: open-access


prompt:
Hunks one line apart are reported as conflicting.

Two patches against the same base list hunks as [old_start, old_len]. A hunk with length > 0 covers lines start..start+len-1; a zero-length hunk is an insertion after line start and sits at start+0.5. Hunks conflict when their spans overlap or are adjacent (within one line). Return sorted [i, j] index pairs of conflicting hunks from the first and second patch.

split: open-access


broken_source:
"""Failure Map reference implementation. Python standard library only."""
import json
import re
N = 1
observations = []
def solve(lines):
    m = re.match(r'@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@(.*)$', lines[0])
    a, an, c, cn, tail = m.groups()
    def fmt(s, cnt):
        return s + ',' + (cnt or '0')
    out = ['@@ -%s +%s @@%s' % (fmt(c, cn), fmt(a, an), tail)]
    units = []
    for ln in lines[1:]:
        if ln.startswith('\\') and units:
            units[-1].append(ln)
        else:
            units.append([ln])
    dels, adds = [], []
    def flush():
        for u in dels + adds:
            out.extend(u)
        dels.clear()
        adds.clear()
    for u in units:
        tag = u[0][:1]
        if tag == '+':
            dels.append(['-' + u[0][1:]] + u[1:])
        elif tag == '-':
            adds.append(['+' + u[0][1:]] + u[1:])
        else:
            flush()
            out.extend(u)
    flush()
    return out
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
cases = {
    1: [('replacement block', [['@@ -3,2 +3,2 @@ def f():', ' a', '-b', '+B', ' c']], ['@@ -3,2 +3,2 @@ def f():', ' a', '-B', '+b', ' c']), ('omitted counts stay omitted', [['@@ -5 +5 @@', '-x', '+y']], ['@@ -5 +5 @@', '-y', '+x']), ('explicit zero count', [['@@ -0,0 +1,1 @@', '+n0']], ['@@ -1,1 +0,0 @@', '-n0']), ('no-newline marker follows its line', [['@@ -1,2 +1,2 @@', ' k', '-old', '\\ No newline at end of file', '+new', '\\ No newline at end of file']], ['@@ -1,2 +1,2 @@', ' k', '-new', '\\ No newline at end of file', '+old', '\\ No newline at end of file']), ('several blocks', [['@@ -1,6 +1,5 @@', '-a', ' b', '+c', '+d', ' e', '-f', '-g', '+h', ' i']], ['@@ -1,5 +1,6 @@', '+a', ' b', '-c', '-d', ' e', '-h', '+f', '+g', ' i']), ('insertion only', [['@@ -2,1 +2,3 @@', ' p', '+q', '+r']], ['@@ -2,3 +2,1 @@', ' p', '-q', '-r']), ('marker after the new side only', [['@@ -4,1 +4,1 @@', '-z', '+z2', '\\ No newline at end of file']], ['@@ -4,1 +4,1 @@', '-z2', '\\ No newline at end of file', '+z']), ('header without trailing text', [['@@ -7,3 +7,3 @@', ' u', '-v', ' w', '+x0']], ['@@ -7,3 +7,3 @@', ' u', '+v', ' w', '-x0'])],
    2: [('replacement block', [['@@ -3,2 +3,2 @@ def f():', ' a', '-b', '+B', ' c']], ['@@ -3,2 +3,2 @@ def f():', ' a', '-B', '+b', ' c']), ('omitted counts stay omitted', [['@@ -5 +5 @@', '-x', '+y']], ['@@ -5 +5 @@', '-y', '+x']), ('explicit zero count', [['@@ -0,0 +1,2 @@', '+n0', '+n1']], ['@@ -1,2 +0,0 @@', '-n0', '-n1']), ('no-newline marker follows its line', [['@@ -1,2 +1,2 @@', ' k', '-old', '\\ No newline at end of file', '+new', '\\ No newline at end of file']], ['@@ -1,2 +1,2 @@', ' k', '-new', '\\ No newline at end of file', '+old', '\\ No newline at end of file']), ('several blocks', [['@@ -1,6 +1,5 @@', '-a', ' b', '+c', '+d', ' e', '-f', '-g', '+h', ' i']], ['@@ -1,5 +1,6 @@', '+a', ' b', '-c', '-d', ' e', '-h', '+f', '+g', ' i']), ('insertion only', [['@@ -2,1 +2,3 @@', ' p', '+q', '+r']], ['@@ -2,3 +2,1 @@', ' p', '-q', '-r']), ('marker after the new side only', [['@@ -4,1 +4,1 @@', '-z', '+z2', '\\ No newline at end of file']], ['@@ -4,1 +4,1 @@', '-z2', '\\ No newline at end of file', '+z']), ('header without trailing text', [['@@ -7,3 +7,4 @@', ' u', '-v', ' w', '+x0', '+x1']], ['@@ -7,4 +7,3 @@', ' u', '+v', ' w', '-x0', '-x1'])],
    3: [('replacement block', [['@@ -3,2 +3,2 @@ def f():', ' a', '-b', '+B', ' c']], ['@@ -3,2 +3,2 @@ def f():', ' a', '-B', '+b', ' c']), ('omitted counts stay omitted', [['@@ -5 +5 @@', '-x', '+y']], ['@@ -5 +5 @@', '-y', '+x']), ('explicit zero count', [['@@ -0,0 +1,3 @@', '+n0', '+n1', '+n2']], ['@@ -1,3 +0,0 @@', '-n0', '-n1', '-n2']), ('no-newline marker follows its line', [['@@ -1,2 +1,2 @@', ' k', '-old', '\\ No newline at end of file', '+new', '\\ No newline at end of file']], ['@@ -1,2 +1,2 @@', ' k', '-new', '\\ No newline at end of file', '+old', '\\ No newline at end of file']), ('several blocks', [['@@ -1,6 +1,5 @@', '-a', ' b', '+c', '+d', ' e', '-f', '-g', '+h', ' i']], ['@@ -1,5 +1,6 @@', '+a', ' b', '-c', '-d', ' e', '-h', '+f', '+g', ' i']), ('insertion only', [['@@ -2,1 +2,3 @@', ' p', '+q', '+r']], ['@@ -2,3 +2,1 @@', ' p', '-q', '-r']), ('marker after the new side only', [['@@ -4,1 +4,1 @@', '-z', '+z2', '\\ No newline at end of file']], ['@@ -4,1 +4,1 @@', '-z2', '\\ No newline at end of file', '+z']), ('header without trailing text', [['@@ -7,3 +7,5 @@', ' u', '-v', ' w', '+x0', '+x1', '+x2']], ['@@ -7,5 +7,3 @@', ' u', '+v', ' w', '-x0', '-x1', '-x2'])],
    4: [('replacement block', [['@@ -3,2 +3,2 @@ def f():', ' a', '-b', '+B', ' c']], ['@@ -3,2 +3,2 @@ def f():', ' a', '-B', '+b', ' c']), ('omitted counts stay omitted', [['@@ -5 +5 @@', '-x', '+y']], ['@@ -5 +5 @@', '-y', '+x']), ('explicit zero count', [['@@ -0,0 +1,4 @@', '+n0', '+n1', '+n2', '+n3']], ['@@ -1,4 +0,0 @@', '-n0', '-n1', '-n2', '-n3']), ('no-newline marker follows its line', [['@@ -1,2 +1,2 @@', ' k', '-old', '\\ No newline at end of file', '+new', '\\ No newline at end of file']], ['@@ -1,2 +1,2 @@', ' k', '-new', '\\ No newline at end of file', '+old', '\\ No newline at end of file']), ('several blocks', [['@@ -1,6 +1,5 @@', '-a', ' b', '+c', '+d', ' e', '-f', '-g', '+h', ' i']], ['@@ -1,5 +1,6 @@', '+a', ' b', '-c', '-d', ' e', '-h', '+f', '+g', ' i']), ('insertion only', [['@@ -2,1 +2,3 @@', ' p', '+q', '+r']], ['@@ -2,3 +2,1 @@', ' p', '-q', '-r']), ('marker after the new side only', [['@@ -4,1 +4,1 @@', '-z', '+z2', '\\ No newline at end of file']], ['@@ -4,1 +4,1 @@', '-z2', '\\ No newline at end of file', '+z']), ('header without trailing text', [['@@ -7,3 +7,6 @@', ' u', '-v', ' w', '+x0', '+x1', '+x2', '+x3']], ['@@ -7,6 +7,3 @@', ' u', '+v', ' w', '-x0', '-x1', '-x2', '-x3'])],
    5: [('replacement block', [['@@ -3,2 +3,2 @@ def f():', ' a', '-b', '+B', ' c']], ['@@ -3,2 +3,2 @@ def f():', ' a', '-B', '+b', ' c']), ('omitted counts stay omitted', [['@@ -5 +5 @@', '-x', '+y']], ['@@ -5 +5 @@', '-y', '+x']), ('explicit zero count', [['@@ -0,0 +1,5 @@', '+n0', '+n1', '+n2', '+n3', '+n4']], ['@@ -1,5 +0,0 @@', '-n0', '-n1', '-n2', '-n3', '-n4']), ('no-newline marker follows its line', [['@@ -1,2 +1,2 @@', ' k', '-old', '\\ No newline at end of file', '+new', '\\ No newline at end of file']], ['@@ -1,2 +1,2 @@', ' k', '-new', '\\ No newline at end of file', '+old', '\\ No newline at end of file']), ('several blocks', [['@@ -1,6 +1,5 @@', '-a', ' b', '+c', '+d', ' e', '-f', '-g', '+h', ' i']], ['@@ -1,5 +1,6 @@', '+a', ' b', '-c', '-d', ' e', '-h', '+f', '+g', ' i']), ('insertion only', [['@@ -2,1 +2,3 @@', ' p', '+q', '+r']], ['@@ -2,3 +2,1 @@', ' p', '-q', '-r']), ('marker after the new side only', [['@@ -4,1 +4,1 @@', '-z', '+z2', '\\ No newline at end of file']], ['@@ -4,1 +4,1 @@', '-z2', '\\ No newline at end of file', '+z']), ('header without trailing text', [['@@ -7,3 +7,7 @@', ' u', '-v', ' w', '+x0', '+x1', '+x2', '+x3', '+x4']], ['@@ -7,7 +7,3 @@', ' u', '+v', ' w', '-x0', '-x1', '-x2', '-x3', '-x4'])],
}[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)

source:
"""Failure Map reference implementation. Python standard library only."""
import json
import re
N = 1
observations = []
def solve(lines):
    m = re.match(r'@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@(.*)$', lines[0])
    a, an, c, cn, tail = m.groups()
    def fmt(s, cnt):
        return s + ',' + (cnt or '1')
    out = ['@@ -%s +%s @@%s' % (fmt(c, cn), fmt(a, an), tail)]
    units = []
    for ln in lines[1:]:
        if ln.startswith('\\') and units:
            units[-1].append(ln)
        else:
            units.append([ln])
    dels, adds = [], []
    def flush():
        for u in dels + adds:
            out.extend(u)
        dels.clear()
        adds.clear()
    for u in units:
        tag = u[0][:1]
        if tag == '+':
            dels.append(['-' + u[0][1:]] + u[1:])
        elif tag == '-':
            adds.append(['+' + u[0][1:]] + u[1:])
        else:
            flush()
            out.extend(u)
    flush()
    return out
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
cases = {
    1: [('replacement block', [['@@ -3,2 +3,2 @@ def f():', ' a', '-b', '+B', ' c']], ['@@ -3,2 +3,2 @@ def f():', ' a', '-B', '+b', ' c']), ('omitted counts stay omitted', [['@@ -5 +5 @@', '-x', '+y']], ['@@ -5 +5 @@', '-y', '+x']), ('explicit zero count', [['@@ -0,0 +1,1 @@', '+n0']], ['@@ -1,1 +0,0 @@', '-n0']), ('no-newline marker follows its line', [['@@ -1,2 +1,2 @@', ' k', '-old', '\\ No newline at end of file', '+new', '\\ No newline at end of file']], ['@@ -1,2 +1,2 @@', ' k', '-new', '\\ No newline at end of file', '+old', '\\ No newline at end of file']), ('several blocks', [['@@ -1,6 +1,5 @@', '-a', ' b', '+c', '+d', ' e', '-f', '-g', '+h', ' i']], ['@@ -1,5 +1,6 @@', '+a', ' b', '-c', '-d', ' e', '-h', '+f', '+g', ' i']), ('insertion only', [['@@ -2,1 +2,3 @@', ' p', '+q', '+r']], ['@@ -2,3 +2,1 @@', ' p', '-q', '-r']), ('marker after the new side only', [['@@ -4,1 +4,1 @@', '-z', '+z2', '\\ No newline at end of file']], ['@@ -4,1 +4,1 @@', '-z2', '\\ No newline at end of file', '+z']), ('header without trailing text', [['@@ -7,3 +7,3 @@', ' u', '-v', ' w', '+x0']], ['@@ -7,3 +7,3 @@', ' u', '+v', ' w', '-x0'])],
    2: [('replacement block', [['@@ -3,2 +3,2 @@ def f():', ' a', '-b', '+B', ' c']], ['@@ -3,2 +3,2 @@ def f():', ' a', '-B', '+b', ' c']), ('omitted counts stay omitted', [['@@ -5 +5 @@', '-x', '+y']], ['@@ -5 +5 @@', '-y', '+x']), ('explicit zero count', [['@@ -0,0 +1,2 @@', '+n0', '+n1']], ['@@ -1,2 +0,0 @@', '-n0', '-n1']), ('no-newline marker follows its line', [['@@ -1,2 +1,2 @@', ' k', '-old', '\\ No newline at end of file', '+new', '\\ No newline at end of file']], ['@@ -1,2 +1,2 @@', ' k', '-new', '\\ No newline at end of file', '+old', '\\ No newline at end of file']), ('several blocks', [['@@ -1,6 +1,5 @@', '-a', ' b', '+c', '+d', ' e', '-f', '-g', '+h', ' i']], ['@@ -1,5 +1,6 @@', '+a', ' b', '-c', '-d', ' e', '-h', '+f', '+g', ' i']), ('insertion only', [['@@ -2,1 +2,3 @@', ' p', '+q', '+r']], ['@@ -2,3 +2,1 @@', ' p', '-q', '-r']), ('marker after the new side only', [['@@ -4,1 +4,1 @@', '-z', '+z2', '\\ No newline at end of file']], ['@@ -4,1 +4,1 @@', '-z2', '\\ No newline at end of file', '+z']), ('header without trailing text', [['@@ -7,3 +7,4 @@', ' u', '-v', ' w', '+x0', '+x1']], ['@@ -7,4 +7,3 @@', ' u', '+v', ' w', '-x0', '-x1'])],
    3: [('replacement block', [['@@ -3,2 +3,2 @@ def f():', ' a', '-b', '+B', ' c']], ['@@ -3,2 +3,2 @@ def f():', ' a', '-B', '+b', ' c']), ('omitted counts stay omitted', [['@@ -5 +5 @@', '-x', '+y']], ['@@ -5 +5 @@', '-y', '+x']), ('explicit zero count', [['@@ -0,0 +1,3 @@', '+n0', '+n1', '+n2']], ['@@ -1,3 +0,0 @@', '-n0', '-n1', '-n2']), ('no-newline marker follows its line', [['@@ -1,2 +1,2 @@', ' k', '-old', '\\ No newline at end of file', '+new', '\\ No newline at end of file']], ['@@ -1,2 +1,2 @@', ' k', '-new', '\\ No newline at end of file', '+old', '\\ No newline at end of file']), ('several blocks', [['@@ -1,6 +1,5 @@', '-a', ' b', '+c', '+d', ' e', '-f', '-g', '+h', ' i']], ['@@ -1,5 +1,6 @@', '+a', ' b', '-c', '-d', ' e', '-h', '+f', '+g', ' i']), ('insertion only', [['@@ -2,1 +2,3 @@', ' p', '+q', '+r']], ['@@ -2,3 +2,1 @@', ' p', '-q', '-r']), ('marker after the new side only', [['@@ -4,1 +4,1 @@', '-z', '+z2', '\\ No newline at end of file']], ['@@ -4,1 +4,1 @@', '-z2', '\\ No newline at end of file', '+z']), ('header without trailing text', [['@@ -7,3 +7,5 @@', ' u', '-v', ' w', '+x0', '+x1', '+x2']], ['@@ -7,5 +7,3 @@', ' u', '+v', ' w', '-x0', '-x1', '-x2'])],
    4: [('replacement block', [['@@ -3,2 +3,2 @@ def f():', ' a', '-b', '+B', ' c']], ['@@ -3,2 +3,2 @@ def f():', ' a', '-B', '+b', ' c']), ('omitted counts stay omitted', [['@@ -5 +5 @@', '-x', '+y']], ['@@ -5 +5 @@', '-y', '+x']), ('explicit zero count', [['@@ -0,0 +1,4 @@', '+n0', '+n1', '+n2', '+n3']], ['@@ -1,4 +0,0 @@', '-n0', '-n1', '-n2', '-n3']), ('no-newline marker follows its line', [['@@ -1,2 +1,2 @@', ' k', '-old', '\\ No newline at end of file', '+new', '\\ No newline at end of file']], ['@@ -1,2 +1,2 @@', ' k', '-new', '\\ No newline at end of file', '+old', '\\ No newline at end of file']), ('several blocks', [['@@ -1,6 +1,5 @@', '-a', ' b', '+c', '+d', ' e', '-f', '-g', '+h', ' i']], ['@@ -1,5 +1,6 @@', '+a', ' b', '-c', '-d', ' e', '-h', '+f', '+g', ' i']), ('insertion only', [['@@ -2,1 +2,3 @@', ' p', '+q', '+r']], ['@@ -2,3 +2,1 @@', ' p', '-q', '-r']), ('marker after the new side only', [['@@ -4,1 +4,1 @@', '-z', '+z2', '\\ No newline at end of file']], ['@@ -4,1 +4,1 @@', '-z2', '\\ No newline at end of file', '+z']), ('header without trailing text', [['@@ -7,3 +7,6 @@', ' u', '-v', ' w', '+x0', '+x1', '+x2', '+x3']], ['@@ -7,6 +7,3 @@', ' u', '+v', ' w', '-x0', '-x1', '-x2', '-x3'])],
    5: [('replacement block', [['@@ -3,2 +3,2 @@ def f():', ' a', '-b', '+B', ' c']], ['@@ -3,2 +3,2 @@ def f():', ' a', '-B', '+b', ' c']), ('omitted counts stay omitted', [['@@ -5 +5 @@', '-x', '+y']], ['@@ -5 +5 @@', '-y', '+x']), ('explicit zero count', [['@@ -0,0 +1,5 @@', '+n0', '+n1', '+n2', '+n3', '+n4']], ['@@ -1,5 +0,0 @@', '-n0', '-n1', '-n2', '-n3', '-n4']), ('no-newline marker follows its line', [['@@ -1,2 +1,2 @@', ' k', '-old', '\\ No newline at end of file', '+new', '\\ No newline at end of file']], ['@@ -1,2 +1,2 @@', ' k', '-new', '\\ No newline at end of file', '+old', '\\ No newline at end of file']), ('several blocks', [['@@ -1,6 +1,5 @@', '-a', ' b', '+c', '+d', ' e', '-f', '-g', '+h', ' i']], ['@@ -1,5 +1,6 @@', '+a', ' b', '-c', '-d', ' e', '-h', '+f', '+g', ' i']), ('insertion only', [['@@ -2,1 +2,3 @@', ' p', '+q', '+r']], ['@@ -2,3 +2,1 @@', ' p', '-q', '-r']), ('marker after the new side only', [['@@ -4,1 +4,1 @@', '-z', '+z2', '\\ No newline at end of file']], ['@@ -4,1 +4,1 @@', '-z2', '\\ No newline at end of file', '+z']), ('header without trailing text', [['@@ -7,3 +7,7 @@', ' u', '-v', ' w', '+x0', '+x1', '+x2', '+x3', '+x4']], ['@@ -7,7 +7,3 @@', ' u', '+v', ' w', '-x0', '-x1', '-x2', '-x3', '-x4'])],
}[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)

prompt:
Reversing a single-line hunk produces a header claiming an empty range.

Reverse one unified hunk: swap the old and new ranges in the header, keeping each range's count omitted if it was omitted and keeping any trailing header text; swap "-" and "+" on body lines; within each run of changed lines emit the (new) removed lines before the (new) added lines; a "\" marker line stays attached to the line it follows.

split: open-access


broken_source:
"""Failure Map reference implementation. Python standard library only."""
import json
import re
N = 1
observations = []
def solve(lines):
    m = re.match(r'@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@(.*)$', lines[0])
    a, an, c, cn, tail = m.groups()
    def fmt(s, cnt):
        return s if cnt is None else s + ',' + cnt
    out = ['@@ -%s +%s @@%s' % (fmt(c, an), fmt(a, cn), tail)]
    units = []
    for ln in lines[1:]:
        if ln.startswith('\\') and units:
            units[-1].append(ln)
        else:
            units.append([ln])
    dels, adds = [], []
    def flush():
        for u in dels + adds:
            out.extend(u)
        dels.clear()
        adds.clear()
    for u in units:
        tag = u[0][:1]
        if tag == '+':
            dels.append(['-' + u[0][1:]] + u[1:])
        elif tag == '-':
            adds.append(['+' + u[0][1:]] + u[1:])
        else:
            flush()
            out.extend(u)
    flush()
    return out
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
cases = {
    1: [('replacement block', [['@@ -3,2 +3,2 @@ def f():', ' a', '-b', '+B', ' c']], ['@@ -3,2 +3,2 @@ def f():', ' a', '-B', '+b', ' c']), ('omitted counts stay omitted', [['@@ -5 +5 @@', '-x', '+y']], ['@@ -5 +5 @@', '-y', '+x']), ('explicit zero count', [['@@ -0,0 +1,1 @@', '+n0']], ['@@ -1,1 +0,0 @@', '-n0']), ('no-newline marker follows its line', [['@@ -1,2 +1,2 @@', ' k', '-old', '\\ No newline at end of file', '+new', '\\ No newline at end of file']], ['@@ -1,2 +1,2 @@', ' k', '-new', '\\ No newline at end of file', '+old', '\\ No newline at end of file']), ('several blocks', [['@@ -1,6 +1,5 @@', '-a', ' b', '+c', '+d', ' e', '-f', '-g', '+h', ' i']], ['@@ -1,5 +1,6 @@', '+a', ' b', '-c', '-d', ' e', '-h', '+f', '+g', ' i']), ('insertion only', [['@@ -2,1 +2,3 @@', ' p', '+q', '+r']], ['@@ -2,3 +2,1 @@', ' p', '-q', '-r']), ('marker after the new side only', [['@@ -4,1 +4,1 @@', '-z', '+z2', '\\ No newline at end of file']], ['@@ -4,1 +4,1 @@', '-z2', '\\ No newline at end of file', '+z']), ('header without trailing text', [['@@ -7,3 +7,3 @@', ' u', '-v', ' w', '+x0']], ['@@ -7,3 +7,3 @@', ' u', '+v', ' w', '-x0'])],
    2: [('replacement block', [['@@ -3,2 +3,2 @@ def f():', ' a', '-b', '+B', ' c']], ['@@ -3,2 +3,2 @@ def f():', ' a', '-B', '+b', ' c']), ('omitted counts stay omitted', [['@@ -5 +5 @@', '-x', '+y']], ['@@ -5 +5 @@', '-y', '+x']), ('explicit zero count', [['@@ -0,0 +1,2 @@', '+n0', '+n1']], ['@@ -1,2 +0,0 @@', '-n0', '-n1']), ('no-newline marker follows its line', [['@@ -1,2 +1,2 @@', ' k', '-old', '\\ No newline at end of file', '+new', '\\ No newline at end of file']], ['@@ -1,2 +1,2 @@', ' k', '-new', '\\ No newline at end of file', '+old', '\\ No newline at end of file']), ('several blocks', [['@@ -1,6 +1,5 @@', '-a', ' b', '+c', '+d', ' e', '-f', '-g', '+h', ' i']], ['@@ -1,5 +1,6 @@', '+a', ' b', '-c', '-d', ' e', '-h', '+f', '+g', ' i']), ('insertion only', [['@@ -2,1 +2,3 @@', ' p', '+q', '+r']], ['@@ -2,3 +2,1 @@', ' p', '-q', '-r']), ('marker after the new side only', [['@@ -4,1 +4,1 @@', '-z', '+z2', '\\ No newline at end of file']], ['@@ -4,1 +4,1 @@', '-z2', '\\ No newline at end of file', '+z']), ('header without trailing text', [['@@ -7,3 +7,4 @@', ' u', '-v', ' w', '+x0', '+x1']], ['@@ -7,4 +7,3 @@', ' u', '+v', ' w', '-x0', '-x1'])],
    3: [('replacement block', [['@@ -3,2 +3,2 @@ def f():', ' a', '-b', '+B', ' c']], ['@@ -3,2 +3,2 @@ def f():', ' a', '-B', '+b', ' c']), ('omitted counts stay omitted', [['@@ -5 +5 @@', '-x', '+y']], ['@@ -5 +5 @@', '-y', '+x']), ('explicit zero count', [['@@ -0,0 +1,3 @@', '+n0', '+n1', '+n2']], ['@@ -1,3 +0,0 @@', '-n0', '-n1', '-n2']), ('no-newline marker follows its line', [['@@ -1,2 +1,2 @@', ' k', '-old', '\\ No newline at end of file', '+new', '\\ No newline at end of file']], ['@@ -1,2 +1,2 @@', ' k', '-new', '\\ No newline at end of file', '+old', '\\ No newline at end of file']), ('several blocks', [['@@ -1,6 +1,5 @@', '-a', ' b', '+c', '+d', ' e', '-f', '-g', '+h', ' i']], ['@@ -1,5 +1,6 @@', '+a', ' b', '-c', '-d', ' e', '-h', '+f', '+g', ' i']), ('insertion only', [['@@ -2,1 +2,3 @@', ' p', '+q', '+r']], ['@@ -2,3 +2,1 @@', ' p', '-q', '-r']), ('marker after the new side only', [['@@ -4,1 +4,1 @@', '-z', '+z2', '\\ No newline at end of file']], ['@@ -4,1 +4,1 @@', '-z2', '\\ No newline at end of file', '+z']), ('header without trailing text', [['@@ -7,3 +7,5 @@', ' u', '-v', ' w', '+x0', '+x1', '+x2']], ['@@ -7,5 +7,3 @@', ' u', '+v', ' w', '-x0', '-x1', '-x2'])],
    4: [('replacement block', [['@@ -3,2 +3,2 @@ def f():', ' a', '-b', '+B', ' c']], ['@@ -3,2 +3,2 @@ def f():', ' a', '-B', '+b', ' c']), ('omitted counts stay omitted', [['@@ -5 +5 @@', '-x', '+y']], ['@@ -5 +5 @@', '-y', '+x']), ('explicit zero count', [['@@ -0,0 +1,4 @@', '+n0', '+n1', '+n2', '+n3']], ['@@ -1,4 +0,0 @@', '-n0', '-n1', '-n2', '-n3']), ('no-newline marker follows its line', [['@@ -1,2 +1,2 @@', ' k', '-old', '\\ No newline at end of file', '+new', '\\ No newline at end of file']], ['@@ -1,2 +1,2 @@', ' k', '-new', '\\ No newline at end of file', '+old', '\\ No newline at end of file']), ('several blocks', [['@@ -1,6 +1,5 @@', '-a', ' b', '+c', '+d', ' e', '-f', '-g', '+h', ' i']], ['@@ -1,5 +1,6 @@', '+a', ' b', '-c', '-d', ' e', '-h', '+f', '+g', ' i']), ('insertion only', [['@@ -2,1 +2,3 @@', ' p', '+q', '+r']], ['@@ -2,3 +2,1 @@', ' p', '-q', '-r']), ('marker after the new side only', [['@@ -4,1 +4,1 @@', '-z', '+z2', '\\ No newline at end of file']], ['@@ -4,1 +4,1 @@', '-z2', '\\ No newline at end of file', '+z']), ('header without trailing text', [['@@ -7,3 +7,6 @@', ' u', '-v', ' w', '+x0', '+x1', '+x2', '+x3']], ['@@ -7,6 +7,3 @@', ' u', '+v', ' w', '-x0', '-x1', '-x2', '-x3'])],
    5: [('replacement block', [['@@ -3,2 +3,2 @@ def f():', ' a', '-b', '+B', ' c']], ['@@ -3,2 +3,2 @@ def f():', ' a', '-B', '+b', ' c']), ('omitted counts stay omitted', [['@@ -5 +5 @@', '-x', '+y']], ['@@ -5 +5 @@', '-y', '+x']), ('explicit zero count', [['@@ -0,0 +1,5 @@', '+n0', '+n1', '+n2', '+n3', '+n4']], ['@@ -1,5 +0,0 @@', '-n0', '-n1', '-n2', '-n3', '-n4']), ('no-newline marker follows its line', [['@@ -1,2 +1,2 @@', ' k', '-old', '\\ No newline at end of file', '+new', '\\ No newline at end of file']], ['@@ -1,2 +1,2 @@', ' k', '-new', '\\ No newline at end of file', '+old', '\\ No newline at end of file']), ('several blocks', [['@@ -1,6 +1,5 @@', '-a', ' b', '+c', '+d', ' e', '-f', '-g', '+h', ' i']], ['@@ -1,5 +1,6 @@', '+a', ' b', '-c', '-d', ' e', '-h', '+f', '+g', ' i']), ('insertion only', [['@@ -2,1 +2,3 @@', ' p', '+q', '+r']], ['@@ -2,3 +2,1 @@', ' p', '-q', '-r']), ('marker after the new side only', [['@@ -4,1 +4,1 @@', '-z', '+z2', '\\ No newline at end of file']], ['@@ -4,1 +4,1 @@', '-z2', '\\ No newline at end of file', '+z']), ('header without trailing text', [['@@ -7,3 +7,7 @@', ' u', '-v', ' w', '+x0', '+x1', '+x2', '+x3', '+x4']], ['@@ -7,7 +7,3 @@', ' u', '+v', ' w', '-x0', '-x1', '-x2', '-x3', '-x4'])],
}[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)

source:
"""Failure Map reference implementation. Python standard library only."""
import json
import re
N = 1
observations = []
def solve(lines):
    m = re.match(r'@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@(.*)$', lines[0])
    a, an, c, cn, tail = m.groups()
    def fmt(s, cnt):
        return s if cnt is None else s + ',' + cnt
    out = ['@@ -%s +%s @@%s' % (fmt(a, cn), fmt(c, an), tail)]
    units = []
    for ln in lines[1:]:
        if ln.startswith('\\') and units:
            units[-1].append(ln)
        else:
            units.append([ln])
    dels, adds = [], []
    def flush():
        for u in dels + adds:
            out.extend(u)
        dels.clear()
        adds.clear()
    for u in units:
        tag = u[0][:1]
        if tag == '+':
            dels.append(['-' + u[0][1:]] + u[1:])
        elif tag == '-':
            adds.append(['+' + u[0][1:]] + u[1:])
        else:
            flush()
            out.extend(u)
    flush()
    return out
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
cases = {
    1: [('replacement block', [['@@ -3,2 +3,2 @@ def f():', ' a', '-b', '+B', ' c']], ['@@ -3,2 +3,2 @@ def f():', ' a', '-B', '+b', ' c']), ('omitted counts stay omitted', [['@@ -5 +5 @@', '-x', '+y']], ['@@ -5 +5 @@', '-y', '+x']), ('explicit zero count', [['@@ -0,0 +1,1 @@', '+n0']], ['@@ -1,1 +0,0 @@', '-n0']), ('no-newline marker follows its line', [['@@ -1,2 +1,2 @@', ' k', '-old', '\\ No newline at end of file', '+new', '\\ No newline at end of file']], ['@@ -1,2 +1,2 @@', ' k', '-new', '\\ No newline at end of file', '+old', '\\ No newline at end of file']), ('several blocks', [['@@ -1,6 +1,5 @@', '-a', ' b', '+c', '+d', ' e', '-f', '-g', '+h', ' i']], ['@@ -1,5 +1,6 @@', '+a', ' b', '-c', '-d', ' e', '-h', '+f', '+g', ' i']), ('insertion only', [['@@ -2,1 +2,3 @@', ' p', '+q', '+r']], ['@@ -2,3 +2,1 @@', ' p', '-q', '-r']), ('marker after the new side only', [['@@ -4,1 +4,1 @@', '-z', '+z2', '\\ No newline at end of file']], ['@@ -4,1 +4,1 @@', '-z2', '\\ No newline at end of file', '+z']), ('header without trailing text', [['@@ -7,3 +7,3 @@', ' u', '-v', ' w', '+x0']], ['@@ -7,3 +7,3 @@', ' u', '+v', ' w', '-x0'])],
    2: [('replacement block', [['@@ -3,2 +3,2 @@ def f():', ' a', '-b', '+B', ' c']], ['@@ -3,2 +3,2 @@ def f():', ' a', '-B', '+b', ' c']), ('omitted counts stay omitted', [['@@ -5 +5 @@', '-x', '+y']], ['@@ -5 +5 @@', '-y', '+x']), ('explicit zero count', [['@@ -0,0 +1,2 @@', '+n0', '+n1']], ['@@ -1,2 +0,0 @@', '-n0', '-n1']), ('no-newline marker follows its line', [['@@ -1,2 +1,2 @@', ' k', '-old', '\\ No newline at end of file', '+new', '\\ No newline at end of file']], ['@@ -1,2 +1,2 @@', ' k', '-new', '\\ No newline at end of file', '+old', '\\ No newline at end of file']), ('several blocks', [['@@ -1,6 +1,5 @@', '-a', ' b', '+c', '+d', ' e', '-f', '-g', '+h', ' i']], ['@@ -1,5 +1,6 @@', '+a', ' b', '-c', '-d', ' e', '-h', '+f', '+g', ' i']), ('insertion only', [['@@ -2,1 +2,3 @@', ' p', '+q', '+r']], ['@@ -2,3 +2,1 @@', ' p', '-q', '-r']), ('marker after the new side only', [['@@ -4,1 +4,1 @@', '-z', '+z2', '\\ No newline at end of file']], ['@@ -4,1 +4,1 @@', '-z2', '\\ No newline at end of file', '+z']), ('header without trailing text', [['@@ -7,3 +7,4 @@', ' u', '-v', ' w', '+x0', '+x1']], ['@@ -7,4 +7,3 @@', ' u', '+v', ' w', '-x0', '-x1'])],
    3: [('replacement block', [['@@ -3,2 +3,2 @@ def f():', ' a', '-b', '+B', ' c']], ['@@ -3,2 +3,2 @@ def f():', ' a', '-B', '+b', ' c']), ('omitted counts stay omitted', [['@@ -5 +5 @@', '-x', '+y']], ['@@ -5 +5 @@', '-y', '+x']), ('explicit zero count', [['@@ -0,0 +1,3 @@', '+n0', '+n1', '+n2']], ['@@ -1,3 +0,0 @@', '-n0', '-n1', '-n2']), ('no-newline marker follows its line', [['@@ -1,2 +1,2 @@', ' k', '-old', '\\ No newline at end of file', '+new', '\\ No newline at end of file']], ['@@ -1,2 +1,2 @@', ' k', '-new', '\\ No newline at end of file', '+old', '\\ No newline at end of file']), ('several blocks', [['@@ -1,6 +1,5 @@', '-a', ' b', '+c', '+d', ' e', '-f', '-g', '+h', ' i']], ['@@ -1,5 +1,6 @@', '+a', ' b', '-c', '-d', ' e', '-h', '+f', '+g', ' i']), ('insertion only', [['@@ -2,1 +2,3 @@', ' p', '+q', '+r']], ['@@ -2,3 +2,1 @@', ' p', '-q', '-r']), ('marker after the new side only', [['@@ -4,1 +4,1 @@', '-z', '+z2', '\\ No newline at end of file']], ['@@ -4,1 +4,1 @@', '-z2', '\\ No newline at end of file', '+z']), ('header without trailing text', [['@@ -7,3 +7,5 @@', ' u', '-v', ' w', '+x0', '+x1', '+x2']], ['@@ -7,5 +7,3 @@', ' u', '+v', ' w', '-x0', '-x1', '-x2'])],
    4: [('replacement block', [['@@ -3,2 +3,2 @@ def f():', ' a', '-b', '+B', ' c']], ['@@ -3,2 +3,2 @@ def f():', ' a', '-B', '+b', ' c']), ('omitted counts stay omitted', [['@@ -5 +5 @@', '-x', '+y']], ['@@ -5 +5 @@', '-y', '+x']), ('explicit zero count', [['@@ -0,0 +1,4 @@', '+n0', '+n1', '+n2', '+n3']], ['@@ -1,4 +0,0 @@', '-n0', '-n1', '-n2', '-n3']), ('no-newline marker follows its line', [['@@ -1,2 +1,2 @@', ' k', '-old', '\\ No newline at end of file', '+new', '\\ No newline at end of file']], ['@@ -1,2 +1,2 @@', ' k', '-new', '\\ No newline at end of file', '+old', '\\ No newline at end of file']), ('several blocks', [['@@ -1,6 +1,5 @@', '-a', ' b', '+c', '+d', ' e', '-f', '-g', '+h', ' i']], ['@@ -1,5 +1,6 @@', '+a', ' b', '-c', '-d', ' e', '-h', '+f', '+g', ' i']), ('insertion only', [['@@ -2,1 +2,3 @@', ' p', '+q', '+r']], ['@@ -2,3 +2,1 @@', ' p', '-q', '-r']), ('marker after the new side only', [['@@ -4,1 +4,1 @@', '-z', '+z2', '\\ No newline at end of file']], ['@@ -4,1 +4,1 @@', '-z2', '\\ No newline at end of file', '+z']), ('header without trailing text', [['@@ -7,3 +7,6 @@', ' u', '-v', ' w', '+x0', '+x1', '+x2', '+x3']], ['@@ -7,6 +7,3 @@', ' u', '+v', ' w', '-x0', '-x1', '-x2', '-x3'])],
    5: [('replacement block', [['@@ -3,2 +3,2 @@ def f():', ' a', '-b', '+B', ' c']], ['@@ -3,2 +3,2 @@ def f():', ' a', '-B', '+b', ' c']), ('omitted counts stay omitted', [['@@ -5 +5 @@', '-x', '+y']], ['@@ -5 +5 @@', '-y', '+x']), ('explicit zero count', [['@@ -0,0 +1,5 @@', '+n0', '+n1', '+n2', '+n3', '+n4']], ['@@ -1,5 +0,0 @@', '-n0', '-n1', '-n2', '-n3', '-n4']), ('no-newline marker follows its line', [['@@ -1,2 +1,2 @@', ' k', '-old', '\\ No newline at end of file', '+new', '\\ No newline at end of file']], ['@@ -1,2 +1,2 @@', ' k', '-new', '\\ No newline at end of file', '+old', '\\ No newline at end of file']), ('several blocks', [['@@ -1,6 +1,5 @@', '-a', ' b', '+c', '+d', ' e', '-f', '-g', '+h', ' i']], ['@@ -1,5 +1,6 @@', '+a', ' b', '-c', '-d', ' e', '-h', '+f', '+g', ' i']), ('insertion only', [['@@ -2,1 +2,3 @@', ' p', '+q', '+r']], ['@@ -2,3 +2,1 @@', ' p', '-q', '-r']), ('marker after the new side only', [['@@ -4,1 +4,1 @@', '-z', '+z2', '\\ No newline at end of file']], ['@@ -4,1 +4,1 @@', '-z2', '\\ No newline at end of file', '+z']), ('header without trailing text', [['@@ -7,3 +7,7 @@', ' u', '-v', ' w', '+x0', '+x1', '+x2', '+x3', '+x4']], ['@@ -7,7 +7,3 @@', ' u', '+v', ' w', '-x0', '-x1', '-x2', '-x3', '-x4'])],
}[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)

prompt:
The reversed hunk's header counts disagree with its body.

Reverse one unified hunk: swap the old and new ranges in the header, keeping each range's count omitted if it was omitted and keeping any trailing header text; swap "-" and "+" on body lines; within each run of changed lines emit the (new) removed lines before the (new) added lines; a "\" marker line stays attached to the line it follows.

split: open-access