FA-83251 / Go territory scoring / Open access
Replay stops at the first pass · case 01
Moves after an early pass are ignored.
ROOT CAUSE
The pass branch breaks out of the loop.
VERIFIED REPAIR
Skip passes and continue replaying.
Unsuccessful approach: Handing a pass stone to the opponent applies AGA pass rules not in this contract.
Case contract
Input [size, moves]; each move is [colour, row, col] or [colour, "pass"]. Replay with captures; captured stones are prisoners of the mover; occupied or suicidal moves stop replay with ["illegal", index]. Return [prisoners_B, prisoners_W, final_board_rows].
Why this case matters
Go servers and scoring tools compute this value automatically; a wrong answer changes a game result.
1 / The failure
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(x):
size, moves = x
g = [['.'] * size for _ in range(size)]
pris = {'B': 0, 'W': 0}
def chain(i, j):
col = g[i][j]
seen = {(i, j)}
todo = [(i, j)]
libs = 0
while todo:
a, b = todo.pop()
for p, q in ((a - 1, b), (a, b + 1), (a + 1, b), (a, b - 1)):
if 0 <= p < size and 0 <= q < size:
if g[p][q] == '.':
libs += 1
elif g[p][q] == col and (p, q) not in seen:
seen.add((p, q))
todo.append((p, q))
return seen, libs
for idx, mv in enumerate(moves):
if mv[1] == 'pass':
break
col, r, c = mv
if g[r][c] != '.':
return ['illegal', idx]
g[r][c] = col
opp = 'B' if col == 'W' else 'W'
for p, q in ((r - 1, c), (r, c + 1), (r + 1, c), (r, c - 1)):
if 0 <= p < size and 0 <= q < size and g[p][q] == opp:
dead, libs = chain(p, q)
if libs == 0:
for s, t in dead:
g[s][t] = '.'
pris[col] += len(dead)
own, libs = chain(r, c)
if libs == 0:
return ['illegal', idx]
return [pris['B'], pris['W'], [''.join(row) for row in g]]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[[[4, [['B', 1, 3], ['W', 0, 0], ['B', 2, 1], ['W', 'pass'], ['B', 1, 2], ['W', 1, 0]]], [0, 0, ['W...', 'W.BB', '.B..', '....']]], [[4, [['B', 2, 0], ['W', 3, 1], ['B', 2, 0], ['W', 0, 1], ['B', 2, 0], ['W', 1, 3], ['B', 'pass'], ['W', 0, 1], ['B', 2, 3], ['W', 1, 2], ['B', 1, 1], ['W', 1, 0]]], ['illegal', 2]], [[3, [['B', 1, 1], ['W', 0, 1], ['B', 1, 1], ['W', 1, 1], ['B', 'pass'], ['W', 1, 1], ['B', 2, 0], ['W', 2, 2], ['B', 2, 0], ['W', 1, 1], ['B', 2, 2], ['W', 0, 0], ['B', 'pass'], ['W', 0, 2], ['B', 2, 1]]], ['illegal', 2]], [[3, [['B', 0, 1], ['W', 1, 0], ['B', 2, 1], ['W', 1, 0], ['B', 'pass'], ['W', 0, 0], ['B', 1, 1], ['W', 1, 1], ['B', 1, 1], ['W', 1, 2], ['B', 2, 0], ['W', 1, 1], ['B', 2, 2], ['W', 2, 1], ['B', 0, 0]]], ['illegal', 3]], [[4, [['B', 3, 0], ['W', 2, 1], ['B', 3, 1], ['W', 3, 0], ['B', 0, 0], ['W', 1, 0], ['B', 'pass']]], ['illegal', 3]], [[4, [['B', 0, 3], ['W', 0, 2], ['B', 2, 0], ['W', 1, 3], ['B', 2, 3], ['W', 'pass'], ['B', 0, 1], ['W', 1, 0], ['B', 0, 2], ['W', 1, 0], ['B', 2, 1], ['W', 3, 0]]], ['illegal', 8]], [[3, [['B', 2, 0], ['W', 'pass'], ['B', 1, 0], ['W', 2, 1], ['B', 1, 2], ['W', 0, 1], ['B', 0, 2], ['W', 1, 2], ['B', 'pass']]], ['illegal', 7]], [[4, [['B', 1, 1], ['W', 'pass'], ['B', 1, 0], ['W', 'pass'], ['B', 2, 3], ['W', 0, 2], ['B', 'pass']]], [0, 0, ['..W.', 'BB..', '...B', '....']]]], [[[4, [['B', 0, 3], ['W', 0, 2], ['B', 2, 0], ['W', 1, 3], ['B', 2, 3], ['W', 'pass'], ['B', 0, 1], ['W', 1, 0], ['B', 0, 2], ['W', 1, 0], ['B', 2, 1], ['W', 3, 0]]], ['illegal', 8]], [[4, [['B', 2, 0], ['W', 0, 2], ['B', 1, 1], ['W', 3, 0], ['B', 3, 2]]], [0, 0, ['..W.', '.B..', 'B...', 'W.B.']]], [[3, [['B', 2, 1], ['W', 2, 1], ['B', 1, 2], ['W', 2, 2], ['B', 0, 2], ['W', 0, 0], ['B', 1, 1], ['W', 0, 1], ['B', 0, 2]]], ['illegal', 1]], [[4, [['B', 0, 1], ['W', 'pass'], ['B', 1, 3], ['W', 2, 3], ['B', 0, 2], ['W', 2, 0], ['B', 2, 0], ['W', 1, 1], ['B', 'pass'], ['W', 1, 2], ['B', 1, 0], ['W', 3, 2]]], ['illegal', 6]], [[3, [['B', 1, 0], ['W', 2, 2], ['B', 'pass'], ['W', 1, 0], ['B', 1, 2]]], ['illegal', 3]], [[4, [['B', 1, 0], ['W', 2, 0], ['B', 1, 3], ['W', 0, 0], ['B', 1, 1], ['W', 2, 2], ['B', 3, 1], ['W', 1, 2], ['B', 0, 0], ['W', 0, 2], ['B', 1, 0], ['W', 0, 0]]], ['illegal', 8]], [[3, [['B', 0, 1], ['W', 1, 2], ['B', 1, 2]]], ['illegal', 2]], [[3, [['B', 'pass'], ['W', 0, 2], ['B', 2, 2], ['W', 0, 0], ['B', 0, 1], ['W', 2, 0], ['B', 'pass'], ['W', 1, 0]]], [0, 0, ['WBW', 'W..', 'W.B']]]], [[[3, [['B', 1, 0], ['W', 2, 2], ['B', 'pass'], ['W', 1, 0], ['B', 1, 2]]], ['illegal', 3]], [[4, [['B', 3, 1], ['W', 1, 3], ['B', 2, 3], ['W', 2, 0], ['B', 0, 1], ['W', 1, 3], ['B', 'pass'], ['W', 0, 0], ['B', 3, 0], ['W', 'pass'], ['B', 'pass'], ['W', 1, 1], ['B', 0, 2], ['W', 'pass'], ['B', 0, 0]]], ['illegal', 5]], [[4, [['B', 1, 1], ['W', 0, 2], ['B', 2, 3], ['W', 'pass'], ['B', 1, 1], ['W', 0, 2], ['B', 0, 3], ['W', 2, 0], ['B', 2, 2], ['W', 3, 0], ['B', 3, 0]]], ['illegal', 4]], [[3, [['B', 0, 0], ['W', 2, 2], ['B', 2, 1], ['W', 2, 2], ['B', 1, 2], ['W', 2, 2], ['B', 1, 0]]], ['illegal', 3]], [[3, [['B', 1, 2], ['W', 2, 0], ['B', 1, 0], ['W', 0, 1], ['B', 2, 2], ['W', 2, 2], ['B', 1, 2], ['W', 2, 0], ['B', 'pass'], ['W', 2, 0], ['B', 2, 1], ['W', 2, 0], ['B', 0, 2], ['W', 0, 1], ['B', 2, 2]]], ['illegal', 5]], [[3, [['B', 'pass'], ['W', 1, 2], ['B', 0, 0], ['W', 1, 1], ['B', 0, 2], ['W', 0, 1], ['B', 'pass'], ['W', 'pass']]], [0, 1, ['BW.', '.WW', '...']]], [[4, [['B', 3, 2], ['W', 2, 3], ['B', 2, 0], ['W', 1, 0], ['B', 0, 0], ['W', 2, 0], ['B', 'pass'], ['W', 0, 1], ['B', 2, 0]]], ['illegal', 5]], [[3, [['W', 0, 1], ['B', 0, 0], ['W', 1, 0], ['B', 'pass'], ['W', 2, 2]]], [0, 1, ['.W.', 'W..', '..W']]]], [[[3, [['B', 'pass'], ['W', 1, 2], ['B', 0, 0], ['W', 1, 1], ['B', 0, 2], ['W', 0, 1], ['B', 'pass'], ['W', 'pass']]], [0, 1, ['BW.', '.WW', '...']]], [[4, [['B', 0, 3], ['W', 'pass'], ['B', 3, 1], ['W', 3, 3], ['B', 3, 1], ['W', 0, 3], ['B', 1, 3], ['W', 'pass'], ['B', 3, 2], ['W', 'pass'], ['B', 3, 1], ['W', 0, 2], ['B', 3, 0]]], ['illegal', 4]], [[3, [['B', 1, 1], ['W', 2, 1], ['B', 2, 0], ['W', 0, 2], ['B', 0, 2], ['W', 0, 0], ['B', 2, 2], ['W', 2, 0], ['B', 2, 2], ['W', 0, 2], ['B', 2, 2], ['W', 2, 0]]], ['illegal', 4]], [[3, [['B', 1, 0], ['W', 0, 1], ['B', 0, 1], ['W', 0, 2], ['B', 2, 0], ['W', 1, 0], ['B', 0, 0], ['W', 2, 1], ['B', 2, 2], ['W', 2, 0], ['B', 1, 1], ['W', 0, 2], ['B', 1, 1], ['W', 0, 2]]], ['illegal', 2]], [[4, [['B', 0, 3], ['W', 3, 3], ['B', 1, 2], ['W', 0, 1], ['B', 3, 0]]], [0, 0, ['.W.B', '..B.', '....', 'B..W']]], [[4, [['B', 3, 0], ['W', 0, 3], ['B', 0, 2]]], [0, 0, ['..BW', '....', '....', 'B...']]], [[3, [['B', 0, 0], ['W', 1, 1], ['B', 0, 0], ['W', 'pass'], ['B', 0, 0], ['W', 2, 1], ['B', 2, 2], ['W', 2, 1], ['B', 1, 1]]], ['illegal', 2]], [[4, [['B', 2, 3], ['W', 0, 2], ['B', 1, 3], ['W', 'pass'], ['B', 1, 0], ['W', 2, 1], ['B', 3, 0], ['W', 1, 1]]], [0, 0, ['..W.', 'BW.B', '.W.B', 'B...']]]], [[[3, [['B', 2, 2], ['W', 1, 1], ['B', 1, 0], ['W', 2, 1], ['B', 0, 2]]], [0, 0, ['..B', 'BW.', '.WB']]], [[3, [['B', 0, 2], ['W', 0, 1], ['B', 1, 1], ['W', 2, 2], ['B', 0, 2], ['W', 'pass'], ['B', 1, 1], ['W', 'pass'], ['B', 0, 2], ['W', 2, 1], ['B', 'pass'], ['W', 0, 0], ['B', 'pass']]], ['illegal', 4]], [[3, [['B', 1, 1], ['W', 1, 2], ['B', 0, 2]]], [0, 0, ['..B', '.BW', '...']]], [[3, [['B', 2, 1], ['W', 'pass'], ['B', 'pass'], ['W', 0, 0], ['B', 1, 1], ['W', 0, 2], ['B', 0, 2], ['W', 2, 2], ['B', 0, 1]]], ['illegal', 6]], [[3, [['B', 2, 0], ['W', 0, 1], ['B', 1, 0], ['W', 1, 1], ['B', 2, 0], ['W', 1, 0], ['B', 0, 0], ['W', 'pass']]], ['illegal', 4]], [[4, [['B', 2, 3], ['W', 0, 2], ['B', 1, 3], ['W', 'pass'], ['B', 1, 0], ['W', 2, 1], ['B', 3, 0], ['W', 1, 1]]], [0, 0, ['..W.', 'BW.B', '.W.B', 'B...']]], [[4, [['B', 2, 1], ['W', 2, 0], ['B', 2, 1], ['W', 2, 3], ['B', 'pass'], ['W', 0, 0], ['B', 3, 1], ['W', 3, 2], ['B', 1, 1], ['W', 1, 1]]], ['illegal', 2]], [[4, [['B', 3, 0], ['W', 'pass'], ['B', 'pass']]], [0, 0, ['....', '....', '....', 'B...']]]]]
for i, (args, expected) in enumerate(fixtures[N-1]):
check("replay case %d" % i, solve(args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
| Boundary fixture | Actual | Expected | Outcome |
|---|---|---|---|
| replay case 0 | [0, 0, ['W...', '...B', '.B..', '....']] | [0, 0, ['W...', 'W.BB', '.B..', '....']] | Failed |
| replay case 1 | ['illegal', 2] | ['illegal', 2] | Passed |
| replay case 2 | ['illegal', 2] | ['illegal', 2] | Passed |
| replay case 3 | ['illegal', 3] | ['illegal', 3] | Passed |
| replay case 4 | ['illegal', 3] | ['illegal', 3] | Passed |
| replay case 5 | [0, 1, ['..W.', '...W', 'B..B', '....']] | ['illegal', 8] | Failed |
| replay case 6 | [0, 0, ['...', '...', 'B..']] | ['illegal', 7] | Failed |
| replay case 7 | [0, 0, ['....', '.B..', '....', '....']] | [0, 0, ['..W.', 'BB..', '...B', '....']] | Failed |
SHA-256 / 3ed4a651d0c071c55cb5213a76f933d9b6b491ceb5bcfc1677106fec5c65fa68
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(x):
size, moves = x
g = [['.'] * size for _ in range(size)]
pris = {'B': 0, 'W': 0}
def chain(i, j):
col = g[i][j]
seen = {(i, j)}
todo = [(i, j)]
libs = 0
while todo:
a, b = todo.pop()
for p, q in ((a - 1, b), (a, b + 1), (a + 1, b), (a, b - 1)):
if 0 <= p < size and 0 <= q < size:
if g[p][q] == '.':
libs += 1
elif g[p][q] == col and (p, q) not in seen:
seen.add((p, q))
todo.append((p, q))
return seen, libs
for idx, mv in enumerate(moves):
if mv[1] == 'pass':
pris['W' if mv[0] == 'B' else 'B'] += 1
continue
col, r, c = mv
if g[r][c] != '.':
return ['illegal', idx]
g[r][c] = col
opp = 'B' if col == 'W' else 'W'
for p, q in ((r - 1, c), (r, c + 1), (r + 1, c), (r, c - 1)):
if 0 <= p < size and 0 <= q < size and g[p][q] == opp:
dead, libs = chain(p, q)
if libs == 0:
for s, t in dead:
g[s][t] = '.'
pris[col] += len(dead)
own, libs = chain(r, c)
if libs == 0:
return ['illegal', idx]
return [pris['B'], pris['W'], [''.join(row) for row in g]]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[[[4, [['B', 1, 3], ['W', 0, 0], ['B', 2, 1], ['W', 'pass'], ['B', 1, 2], ['W', 1, 0]]], [0, 0, ['W...', 'W.BB', '.B..', '....']]], [[4, [['B', 2, 0], ['W', 3, 1], ['B', 2, 0], ['W', 0, 1], ['B', 2, 0], ['W', 1, 3], ['B', 'pass'], ['W', 0, 1], ['B', 2, 3], ['W', 1, 2], ['B', 1, 1], ['W', 1, 0]]], ['illegal', 2]], [[3, [['B', 1, 1], ['W', 0, 1], ['B', 1, 1], ['W', 1, 1], ['B', 'pass'], ['W', 1, 1], ['B', 2, 0], ['W', 2, 2], ['B', 2, 0], ['W', 1, 1], ['B', 2, 2], ['W', 0, 0], ['B', 'pass'], ['W', 0, 2], ['B', 2, 1]]], ['illegal', 2]], [[3, [['B', 0, 1], ['W', 1, 0], ['B', 2, 1], ['W', 1, 0], ['B', 'pass'], ['W', 0, 0], ['B', 1, 1], ['W', 1, 1], ['B', 1, 1], ['W', 1, 2], ['B', 2, 0], ['W', 1, 1], ['B', 2, 2], ['W', 2, 1], ['B', 0, 0]]], ['illegal', 3]], [[4, [['B', 3, 0], ['W', 2, 1], ['B', 3, 1], ['W', 3, 0], ['B', 0, 0], ['W', 1, 0], ['B', 'pass']]], ['illegal', 3]], [[4, [['B', 0, 3], ['W', 0, 2], ['B', 2, 0], ['W', 1, 3], ['B', 2, 3], ['W', 'pass'], ['B', 0, 1], ['W', 1, 0], ['B', 0, 2], ['W', 1, 0], ['B', 2, 1], ['W', 3, 0]]], ['illegal', 8]], [[3, [['B', 2, 0], ['W', 'pass'], ['B', 1, 0], ['W', 2, 1], ['B', 1, 2], ['W', 0, 1], ['B', 0, 2], ['W', 1, 2], ['B', 'pass']]], ['illegal', 7]], [[4, [['B', 1, 1], ['W', 'pass'], ['B', 1, 0], ['W', 'pass'], ['B', 2, 3], ['W', 0, 2], ['B', 'pass']]], [0, 0, ['..W.', 'BB..', '...B', '....']]]], [[[4, [['B', 0, 3], ['W', 0, 2], ['B', 2, 0], ['W', 1, 3], ['B', 2, 3], ['W', 'pass'], ['B', 0, 1], ['W', 1, 0], ['B', 0, 2], ['W', 1, 0], ['B', 2, 1], ['W', 3, 0]]], ['illegal', 8]], [[4, [['B', 2, 0], ['W', 0, 2], ['B', 1, 1], ['W', 3, 0], ['B', 3, 2]]], [0, 0, ['..W.', '.B..', 'B...', 'W.B.']]], [[3, [['B', 2, 1], ['W', 2, 1], ['B', 1, 2], ['W', 2, 2], ['B', 0, 2], ['W', 0, 0], ['B', 1, 1], ['W', 0, 1], ['B', 0, 2]]], ['illegal', 1]], [[4, [['B', 0, 1], ['W', 'pass'], ['B', 1, 3], ['W', 2, 3], ['B', 0, 2], ['W', 2, 0], ['B', 2, 0], ['W', 1, 1], ['B', 'pass'], ['W', 1, 2], ['B', 1, 0], ['W', 3, 2]]], ['illegal', 6]], [[3, [['B', 1, 0], ['W', 2, 2], ['B', 'pass'], ['W', 1, 0], ['B', 1, 2]]], ['illegal', 3]], [[4, [['B', 1, 0], ['W', 2, 0], ['B', 1, 3], ['W', 0, 0], ['B', 1, 1], ['W', 2, 2], ['B', 3, 1], ['W', 1, 2], ['B', 0, 0], ['W', 0, 2], ['B', 1, 0], ['W', 0, 0]]], ['illegal', 8]], [[3, [['B', 0, 1], ['W', 1, 2], ['B', 1, 2]]], ['illegal', 2]], [[3, [['B', 'pass'], ['W', 0, 2], ['B', 2, 2], ['W', 0, 0], ['B', 0, 1], ['W', 2, 0], ['B', 'pass'], ['W', 1, 0]]], [0, 0, ['WBW', 'W..', 'W.B']]]], [[[3, [['B', 1, 0], ['W', 2, 2], ['B', 'pass'], ['W', 1, 0], ['B', 1, 2]]], ['illegal', 3]], [[4, [['B', 3, 1], ['W', 1, 3], ['B', 2, 3], ['W', 2, 0], ['B', 0, 1], ['W', 1, 3], ['B', 'pass'], ['W', 0, 0], ['B', 3, 0], ['W', 'pass'], ['B', 'pass'], ['W', 1, 1], ['B', 0, 2], ['W', 'pass'], ['B', 0, 0]]], ['illegal', 5]], [[4, [['B', 1, 1], ['W', 0, 2], ['B', 2, 3], ['W', 'pass'], ['B', 1, 1], ['W', 0, 2], ['B', 0, 3], ['W', 2, 0], ['B', 2, 2], ['W', 3, 0], ['B', 3, 0]]], ['illegal', 4]], [[3, [['B', 0, 0], ['W', 2, 2], ['B', 2, 1], ['W', 2, 2], ['B', 1, 2], ['W', 2, 2], ['B', 1, 0]]], ['illegal', 3]], [[3, [['B', 1, 2], ['W', 2, 0], ['B', 1, 0], ['W', 0, 1], ['B', 2, 2], ['W', 2, 2], ['B', 1, 2], ['W', 2, 0], ['B', 'pass'], ['W', 2, 0], ['B', 2, 1], ['W', 2, 0], ['B', 0, 2], ['W', 0, 1], ['B', 2, 2]]], ['illegal', 5]], [[3, [['B', 'pass'], ['W', 1, 2], ['B', 0, 0], ['W', 1, 1], ['B', 0, 2], ['W', 0, 1], ['B', 'pass'], ['W', 'pass']]], [0, 1, ['BW.', '.WW', '...']]], [[4, [['B', 3, 2], ['W', 2, 3], ['B', 2, 0], ['W', 1, 0], ['B', 0, 0], ['W', 2, 0], ['B', 'pass'], ['W', 0, 1], ['B', 2, 0]]], ['illegal', 5]], [[3, [['W', 0, 1], ['B', 0, 0], ['W', 1, 0], ['B', 'pass'], ['W', 2, 2]]], [0, 1, ['.W.', 'W..', '..W']]]], [[[3, [['B', 'pass'], ['W', 1, 2], ['B', 0, 0], ['W', 1, 1], ['B', 0, 2], ['W', 0, 1], ['B', 'pass'], ['W', 'pass']]], [0, 1, ['BW.', '.WW', '...']]], [[4, [['B', 0, 3], ['W', 'pass'], ['B', 3, 1], ['W', 3, 3], ['B', 3, 1], ['W', 0, 3], ['B', 1, 3], ['W', 'pass'], ['B', 3, 2], ['W', 'pass'], ['B', 3, 1], ['W', 0, 2], ['B', 3, 0]]], ['illegal', 4]], [[3, [['B', 1, 1], ['W', 2, 1], ['B', 2, 0], ['W', 0, 2], ['B', 0, 2], ['W', 0, 0], ['B', 2, 2], ['W', 2, 0], ['B', 2, 2], ['W', 0, 2], ['B', 2, 2], ['W', 2, 0]]], ['illegal', 4]], [[3, [['B', 1, 0], ['W', 0, 1], ['B', 0, 1], ['W', 0, 2], ['B', 2, 0], ['W', 1, 0], ['B', 0, 0], ['W', 2, 1], ['B', 2, 2], ['W', 2, 0], ['B', 1, 1], ['W', 0, 2], ['B', 1, 1], ['W', 0, 2]]], ['illegal', 2]], [[4, [['B', 0, 3], ['W', 3, 3], ['B', 1, 2], ['W', 0, 1], ['B', 3, 0]]], [0, 0, ['.W.B', '..B.', '....', 'B..W']]], [[4, [['B', 3, 0], ['W', 0, 3], ['B', 0, 2]]], [0, 0, ['..BW', '....', '....', 'B...']]], [[3, [['B', 0, 0], ['W', 1, 1], ['B', 0, 0], ['W', 'pass'], ['B', 0, 0], ['W', 2, 1], ['B', 2, 2], ['W', 2, 1], ['B', 1, 1]]], ['illegal', 2]], [[4, [['B', 2, 3], ['W', 0, 2], ['B', 1, 3], ['W', 'pass'], ['B', 1, 0], ['W', 2, 1], ['B', 3, 0], ['W', 1, 1]]], [0, 0, ['..W.', 'BW.B', '.W.B', 'B...']]]], [[[3, [['B', 2, 2], ['W', 1, 1], ['B', 1, 0], ['W', 2, 1], ['B', 0, 2]]], [0, 0, ['..B', 'BW.', '.WB']]], [[3, [['B', 0, 2], ['W', 0, 1], ['B', 1, 1], ['W', 2, 2], ['B', 0, 2], ['W', 'pass'], ['B', 1, 1], ['W', 'pass'], ['B', 0, 2], ['W', 2, 1], ['B', 'pass'], ['W', 0, 0], ['B', 'pass']]], ['illegal', 4]], [[3, [['B', 1, 1], ['W', 1, 2], ['B', 0, 2]]], [0, 0, ['..B', '.BW', '...']]], [[3, [['B', 2, 1], ['W', 'pass'], ['B', 'pass'], ['W', 0, 0], ['B', 1, 1], ['W', 0, 2], ['B', 0, 2], ['W', 2, 2], ['B', 0, 1]]], ['illegal', 6]], [[3, [['B', 2, 0], ['W', 0, 1], ['B', 1, 0], ['W', 1, 1], ['B', 2, 0], ['W', 1, 0], ['B', 0, 0], ['W', 'pass']]], ['illegal', 4]], [[4, [['B', 2, 3], ['W', 0, 2], ['B', 1, 3], ['W', 'pass'], ['B', 1, 0], ['W', 2, 1], ['B', 3, 0], ['W', 1, 1]]], [0, 0, ['..W.', 'BW.B', '.W.B', 'B...']]], [[4, [['B', 2, 1], ['W', 2, 0], ['B', 2, 1], ['W', 2, 3], ['B', 'pass'], ['W', 0, 0], ['B', 3, 1], ['W', 3, 2], ['B', 1, 1], ['W', 1, 1]]], ['illegal', 2]], [[4, [['B', 3, 0], ['W', 'pass'], ['B', 'pass']]], [0, 0, ['....', '....', '....', 'B...']]]]]
for i, (args, expected) in enumerate(fixtures[N-1]):
check("replay case %d" % i, solve(args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
| Boundary fixture | Actual | Expected | Outcome |
|---|---|---|---|
| replay case 0 | [1, 0, ['W...', 'W.BB', '.B..', '....']] | [0, 0, ['W...', 'W.BB', '.B..', '....']] | Failed |
| replay case 1 | ['illegal', 2] | ['illegal', 2] | Passed |
| replay case 2 | ['illegal', 2] | ['illegal', 2] | Passed |
| replay case 3 | ['illegal', 3] | ['illegal', 3] | Passed |
| replay case 4 | ['illegal', 3] | ['illegal', 3] | Passed |
| replay case 5 | ['illegal', 8] | ['illegal', 8] | Passed |
| replay case 6 | ['illegal', 7] | ['illegal', 7] | Passed |
| replay case 7 | [2, 1, ['..W.', 'BB..', '...B', '....']] | [0, 0, ['..W.', 'BB..', '...B', '....']] | Failed |
SHA-256 / 8332683675cc8f396ef356467ef3d66da7d16f8f2bf1a973e53f63efe31c1569
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(x):
size, moves = x
g = [['.'] * size for _ in range(size)]
pris = {'B': 0, 'W': 0}
def chain(i, j):
col = g[i][j]
seen = {(i, j)}
todo = [(i, j)]
libs = 0
while todo:
a, b = todo.pop()
for p, q in ((a - 1, b), (a, b + 1), (a + 1, b), (a, b - 1)):
if 0 <= p < size and 0 <= q < size:
if g[p][q] == '.':
libs += 1
elif g[p][q] == col and (p, q) not in seen:
seen.add((p, q))
todo.append((p, q))
return seen, libs
for idx, mv in enumerate(moves):
if mv[1] == 'pass':
continue
col, r, c = mv
if g[r][c] != '.':
return ['illegal', idx]
g[r][c] = col
opp = 'B' if col == 'W' else 'W'
for p, q in ((r - 1, c), (r, c + 1), (r + 1, c), (r, c - 1)):
if 0 <= p < size and 0 <= q < size and g[p][q] == opp:
dead, libs = chain(p, q)
if libs == 0:
for s, t in dead:
g[s][t] = '.'
pris[col] += len(dead)
own, libs = chain(r, c)
if libs == 0:
return ['illegal', idx]
return [pris['B'], pris['W'], [''.join(row) for row in g]]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[[[4, [['B', 1, 3], ['W', 0, 0], ['B', 2, 1], ['W', 'pass'], ['B', 1, 2], ['W', 1, 0]]], [0, 0, ['W...', 'W.BB', '.B..', '....']]], [[4, [['B', 2, 0], ['W', 3, 1], ['B', 2, 0], ['W', 0, 1], ['B', 2, 0], ['W', 1, 3], ['B', 'pass'], ['W', 0, 1], ['B', 2, 3], ['W', 1, 2], ['B', 1, 1], ['W', 1, 0]]], ['illegal', 2]], [[3, [['B', 1, 1], ['W', 0, 1], ['B', 1, 1], ['W', 1, 1], ['B', 'pass'], ['W', 1, 1], ['B', 2, 0], ['W', 2, 2], ['B', 2, 0], ['W', 1, 1], ['B', 2, 2], ['W', 0, 0], ['B', 'pass'], ['W', 0, 2], ['B', 2, 1]]], ['illegal', 2]], [[3, [['B', 0, 1], ['W', 1, 0], ['B', 2, 1], ['W', 1, 0], ['B', 'pass'], ['W', 0, 0], ['B', 1, 1], ['W', 1, 1], ['B', 1, 1], ['W', 1, 2], ['B', 2, 0], ['W', 1, 1], ['B', 2, 2], ['W', 2, 1], ['B', 0, 0]]], ['illegal', 3]], [[4, [['B', 3, 0], ['W', 2, 1], ['B', 3, 1], ['W', 3, 0], ['B', 0, 0], ['W', 1, 0], ['B', 'pass']]], ['illegal', 3]], [[4, [['B', 0, 3], ['W', 0, 2], ['B', 2, 0], ['W', 1, 3], ['B', 2, 3], ['W', 'pass'], ['B', 0, 1], ['W', 1, 0], ['B', 0, 2], ['W', 1, 0], ['B', 2, 1], ['W', 3, 0]]], ['illegal', 8]], [[3, [['B', 2, 0], ['W', 'pass'], ['B', 1, 0], ['W', 2, 1], ['B', 1, 2], ['W', 0, 1], ['B', 0, 2], ['W', 1, 2], ['B', 'pass']]], ['illegal', 7]], [[4, [['B', 1, 1], ['W', 'pass'], ['B', 1, 0], ['W', 'pass'], ['B', 2, 3], ['W', 0, 2], ['B', 'pass']]], [0, 0, ['..W.', 'BB..', '...B', '....']]]], [[[4, [['B', 0, 3], ['W', 0, 2], ['B', 2, 0], ['W', 1, 3], ['B', 2, 3], ['W', 'pass'], ['B', 0, 1], ['W', 1, 0], ['B', 0, 2], ['W', 1, 0], ['B', 2, 1], ['W', 3, 0]]], ['illegal', 8]], [[4, [['B', 2, 0], ['W', 0, 2], ['B', 1, 1], ['W', 3, 0], ['B', 3, 2]]], [0, 0, ['..W.', '.B..', 'B...', 'W.B.']]], [[3, [['B', 2, 1], ['W', 2, 1], ['B', 1, 2], ['W', 2, 2], ['B', 0, 2], ['W', 0, 0], ['B', 1, 1], ['W', 0, 1], ['B', 0, 2]]], ['illegal', 1]], [[4, [['B', 0, 1], ['W', 'pass'], ['B', 1, 3], ['W', 2, 3], ['B', 0, 2], ['W', 2, 0], ['B', 2, 0], ['W', 1, 1], ['B', 'pass'], ['W', 1, 2], ['B', 1, 0], ['W', 3, 2]]], ['illegal', 6]], [[3, [['B', 1, 0], ['W', 2, 2], ['B', 'pass'], ['W', 1, 0], ['B', 1, 2]]], ['illegal', 3]], [[4, [['B', 1, 0], ['W', 2, 0], ['B', 1, 3], ['W', 0, 0], ['B', 1, 1], ['W', 2, 2], ['B', 3, 1], ['W', 1, 2], ['B', 0, 0], ['W', 0, 2], ['B', 1, 0], ['W', 0, 0]]], ['illegal', 8]], [[3, [['B', 0, 1], ['W', 1, 2], ['B', 1, 2]]], ['illegal', 2]], [[3, [['B', 'pass'], ['W', 0, 2], ['B', 2, 2], ['W', 0, 0], ['B', 0, 1], ['W', 2, 0], ['B', 'pass'], ['W', 1, 0]]], [0, 0, ['WBW', 'W..', 'W.B']]]], [[[3, [['B', 1, 0], ['W', 2, 2], ['B', 'pass'], ['W', 1, 0], ['B', 1, 2]]], ['illegal', 3]], [[4, [['B', 3, 1], ['W', 1, 3], ['B', 2, 3], ['W', 2, 0], ['B', 0, 1], ['W', 1, 3], ['B', 'pass'], ['W', 0, 0], ['B', 3, 0], ['W', 'pass'], ['B', 'pass'], ['W', 1, 1], ['B', 0, 2], ['W', 'pass'], ['B', 0, 0]]], ['illegal', 5]], [[4, [['B', 1, 1], ['W', 0, 2], ['B', 2, 3], ['W', 'pass'], ['B', 1, 1], ['W', 0, 2], ['B', 0, 3], ['W', 2, 0], ['B', 2, 2], ['W', 3, 0], ['B', 3, 0]]], ['illegal', 4]], [[3, [['B', 0, 0], ['W', 2, 2], ['B', 2, 1], ['W', 2, 2], ['B', 1, 2], ['W', 2, 2], ['B', 1, 0]]], ['illegal', 3]], [[3, [['B', 1, 2], ['W', 2, 0], ['B', 1, 0], ['W', 0, 1], ['B', 2, 2], ['W', 2, 2], ['B', 1, 2], ['W', 2, 0], ['B', 'pass'], ['W', 2, 0], ['B', 2, 1], ['W', 2, 0], ['B', 0, 2], ['W', 0, 1], ['B', 2, 2]]], ['illegal', 5]], [[3, [['B', 'pass'], ['W', 1, 2], ['B', 0, 0], ['W', 1, 1], ['B', 0, 2], ['W', 0, 1], ['B', 'pass'], ['W', 'pass']]], [0, 1, ['BW.', '.WW', '...']]], [[4, [['B', 3, 2], ['W', 2, 3], ['B', 2, 0], ['W', 1, 0], ['B', 0, 0], ['W', 2, 0], ['B', 'pass'], ['W', 0, 1], ['B', 2, 0]]], ['illegal', 5]], [[3, [['W', 0, 1], ['B', 0, 0], ['W', 1, 0], ['B', 'pass'], ['W', 2, 2]]], [0, 1, ['.W.', 'W..', '..W']]]], [[[3, [['B', 'pass'], ['W', 1, 2], ['B', 0, 0], ['W', 1, 1], ['B', 0, 2], ['W', 0, 1], ['B', 'pass'], ['W', 'pass']]], [0, 1, ['BW.', '.WW', '...']]], [[4, [['B', 0, 3], ['W', 'pass'], ['B', 3, 1], ['W', 3, 3], ['B', 3, 1], ['W', 0, 3], ['B', 1, 3], ['W', 'pass'], ['B', 3, 2], ['W', 'pass'], ['B', 3, 1], ['W', 0, 2], ['B', 3, 0]]], ['illegal', 4]], [[3, [['B', 1, 1], ['W', 2, 1], ['B', 2, 0], ['W', 0, 2], ['B', 0, 2], ['W', 0, 0], ['B', 2, 2], ['W', 2, 0], ['B', 2, 2], ['W', 0, 2], ['B', 2, 2], ['W', 2, 0]]], ['illegal', 4]], [[3, [['B', 1, 0], ['W', 0, 1], ['B', 0, 1], ['W', 0, 2], ['B', 2, 0], ['W', 1, 0], ['B', 0, 0], ['W', 2, 1], ['B', 2, 2], ['W', 2, 0], ['B', 1, 1], ['W', 0, 2], ['B', 1, 1], ['W', 0, 2]]], ['illegal', 2]], [[4, [['B', 0, 3], ['W', 3, 3], ['B', 1, 2], ['W', 0, 1], ['B', 3, 0]]], [0, 0, ['.W.B', '..B.', '....', 'B..W']]], [[4, [['B', 3, 0], ['W', 0, 3], ['B', 0, 2]]], [0, 0, ['..BW', '....', '....', 'B...']]], [[3, [['B', 0, 0], ['W', 1, 1], ['B', 0, 0], ['W', 'pass'], ['B', 0, 0], ['W', 2, 1], ['B', 2, 2], ['W', 2, 1], ['B', 1, 1]]], ['illegal', 2]], [[4, [['B', 2, 3], ['W', 0, 2], ['B', 1, 3], ['W', 'pass'], ['B', 1, 0], ['W', 2, 1], ['B', 3, 0], ['W', 1, 1]]], [0, 0, ['..W.', 'BW.B', '.W.B', 'B...']]]], [[[3, [['B', 2, 2], ['W', 1, 1], ['B', 1, 0], ['W', 2, 1], ['B', 0, 2]]], [0, 0, ['..B', 'BW.', '.WB']]], [[3, [['B', 0, 2], ['W', 0, 1], ['B', 1, 1], ['W', 2, 2], ['B', 0, 2], ['W', 'pass'], ['B', 1, 1], ['W', 'pass'], ['B', 0, 2], ['W', 2, 1], ['B', 'pass'], ['W', 0, 0], ['B', 'pass']]], ['illegal', 4]], [[3, [['B', 1, 1], ['W', 1, 2], ['B', 0, 2]]], [0, 0, ['..B', '.BW', '...']]], [[3, [['B', 2, 1], ['W', 'pass'], ['B', 'pass'], ['W', 0, 0], ['B', 1, 1], ['W', 0, 2], ['B', 0, 2], ['W', 2, 2], ['B', 0, 1]]], ['illegal', 6]], [[3, [['B', 2, 0], ['W', 0, 1], ['B', 1, 0], ['W', 1, 1], ['B', 2, 0], ['W', 1, 0], ['B', 0, 0], ['W', 'pass']]], ['illegal', 4]], [[4, [['B', 2, 3], ['W', 0, 2], ['B', 1, 3], ['W', 'pass'], ['B', 1, 0], ['W', 2, 1], ['B', 3, 0], ['W', 1, 1]]], [0, 0, ['..W.', 'BW.B', '.W.B', 'B...']]], [[4, [['B', 2, 1], ['W', 2, 0], ['B', 2, 1], ['W', 2, 3], ['B', 'pass'], ['W', 0, 0], ['B', 3, 1], ['W', 3, 2], ['B', 1, 1], ['W', 1, 1]]], ['illegal', 2]], [[4, [['B', 3, 0], ['W', 'pass'], ['B', 'pass']]], [0, 0, ['....', '....', '....', 'B...']]]]]
for i, (args, expected) in enumerate(fixtures[N-1]):
check("replay case %d" % i, solve(args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
| Boundary fixture | Actual | Expected | Outcome |
|---|---|---|---|
| replay case 0 | [0, 0, ['W...', 'W.BB', '.B..', '....']] | [0, 0, ['W...', 'W.BB', '.B..', '....']] | Passed |
| replay case 1 | ['illegal', 2] | ['illegal', 2] | Passed |
| replay case 2 | ['illegal', 2] | ['illegal', 2] | Passed |
| replay case 3 | ['illegal', 3] | ['illegal', 3] | Passed |
| replay case 4 | ['illegal', 3] | ['illegal', 3] | Passed |
| replay case 5 | ['illegal', 8] | ['illegal', 8] | Passed |
| replay case 6 | ['illegal', 7] | ['illegal', 7] | Passed |
| replay case 7 | [0, 0, ['..W.', 'BB..', '...B', '....']] | [0, 0, ['..W.', 'BB..', '...B', '....']] | Passed |
SHA-256 / 5863774b35ba071673773ec173f192f0e50f215cfb0427032c75195f43165baa
Verification & scope
Small rectangular toy boards given as strings of B, W and dot; a bounded teaching model of one scoring or bookkeeping rule, not a complete rules engine or server implementation. This reproducer isolates one failure mechanism. Results cover the supplied fixtures. Variants within a family share a test contract and should remain grouped when constructing evaluation splits. Related mechanisms with a shared evaluation_group must also remain together; these controlled models are not independent production incidents.
Observations recorded using Python 3.12.14 at 2026-09-29T14:50:19.960566+00:00.
Case digest / cc60e7378877d96e168d33d55a0506acc1cd1a0a3b8896e6bd41ea00ad223906