FA-83151 / Go territory scoring / Open access
Seki contact is forgotten while flooding a region · case 01
Regions touching seki stones are still counted if the last processed point does not touch them.
ROOT CAUSE
The frozen flag is reset for every popped point.
VERIFIED REPAIR
Initialise the flag once per region and only ever set it.
Unsuccessful approach: Detecting seki contact only from the region seed misses contacts elsewhere in the region.
Case contract
Input [board, seki_points]. Empty regions bordered by exactly one colour are territory, unless the region touches a stone listed as seki or contains a listed empty point. Return [terr_b, terr_w].
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):
board, seki = x
n = len(board)
m = len(board[0])
sk = {tuple(p) for p in seki}
tb = 0
tw = 0
seen = set()
for r in range(n):
for c in range(m):
if board[r][c] != '.' or (r, c) in seen:
continue
seen.add((r, c))
stack = [(r, c)]
size = 0
cols = set()
frozen = False
while stack:
i, j = stack.pop()
frozen = False
size += 1
if (i, j) in sk:
frozen = True
for p, q in ((i, j + 1), (i + 1, j), (i, j - 1), (i - 1, j)):
if not (0 <= p < n and 0 <= q < m):
continue
if board[p][q] == '.':
if (p, q) not in seen:
seen.add((p, q))
stack.append((p, q))
else:
cols.add(board[p][q])
if (p, q) in sk:
frozen = True
if frozen or len(cols) != 1:
continue
if 'B' in cols:
tb += size
else:
tw += size
return [tb, tw]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[[[['..BW..', '..BW..', '..BW..', '..BW..'], [[1, 2], [3, 2], [3, 0]]], [0, 8]], [[['....BW', '....BW', '....BW', '....BW', '....BW', '...WBW', 'W...BW'], []], [0, 0]], [[['...BW..', '.W.BW..', '...BW..', '..WBW..'], [[1, 1]]], [0, 8]], [[['...BW.', 'W..BW.', '...BWB', '.W.BW.', '...BW.'], [[4, 3]]], [0, 0]], [[['....BW', '....BW', '.W..BW', '....BW', '....BW'], [[1, 5], [2, 1]]], [0, 0]], [[['WBW.', '.BW.', 'WBW.', '.BW.', '.BW.', '.BW.'], [[2, 0], [4, 3]]], [0, 0]], [[['.WBW', '..BW', '.WBW', '..BW'], [[2, 3], [2, 0]]], [0, 0]], [[['..B.', '.B..', '.BB.'], [[0, 2]]], [0, 0]]], [[[['.....BW', '.....BW', '.....BW', '.....BW', '.....BW', '.W...BW'], [[4, 6], [2, 6]]], [0, 0]], [[['..BWB', 'W.BW.', '..BW.', '..BW.'], [[3, 2]]], [0, 0]], [[['.W.BWB', '...BW.', '...BW.', '...BW.'], [[2, 4], [0, 5]]], [0, 0]], [[['.BW.B.', '.BW...', '.BW...', '.BW...'], [[1, 1], [0, 4], [3, 3]]], [0, 0]], [[['.WBW.', '..BW.', '..BW.', '..BW.'], []], [0, 4]], [[['....BW', '.W.WBW', '....BW', 'WW.WBW', '..W.BW', '.W..BW', '....BW'], [[2, 5], [1, 2]]], [0, 0]], [[['..BW.', '..BW.', '..BW.', '..BW.', '.WBW.'], [[0, 0]]], [0, 5]], [[['.BW.', '.BW.', '.BW.', '.BW.'], [[2, 2], [1, 0]]], [0, 0]]], [[[['..BWB.', '..BW..', '..BW..', '..BW..', '..BW..'], [[2, 2]]], [0, 0]], [[['.BW.', '.BW.', '.BW.', '.BW.'], [[0, 2], [3, 1], [0, 0]]], [0, 0]], [[['WW.BW.', '...BWB', '...BW.', '.W.BW.'], [[1, 5]]], [0, 0]], [[['..BW.', '..BW.', '..BW.', 'W.BWB', '..BWB', '..BW.', 'W.BW.'], [[3, 3], [0, 1]]], [0, 0]], [[['..BW..', '..BW..', '..BW..', '..BW..', '..BW..', '.WBW..'], [[2, 3]]], [0, 0]], [[['..BW.', '..BW.', '..BW.', 'WWBW.', '.WBW.'], []], [0, 6]], [[['.BW.', '.BWB', '.BW.', '.BWB', '.BW.'], [[4, 3]]], [5, 0]], [[['WBW..', '.BW..', '.BW..', '.BW..', '.BW.B', '.BW..'], [[4, 1]]], [0, 0]]], [[[['.BW..', '.BW..', '.BW..', '.BW..'], [[1, 1], [0, 2], [3, 3]]], [0, 0]], [[['..BW.', '..BW.', '..BWB', '..BW.', 'W.BW.', '..BW.', '..BW.'], [[2, 3], [2, 4], [6, 1]]], [0, 0]], [[['....', '....', '....', '....'], [[0, 0]]], [0, 0]], [[['...', '...', '...'], []], [0, 0]], [[['.B.', 'B.B', '.B.'], [[1, 1]]], [4, 0]], [[['B..W', 'B..W', 'B..W', 'B..W'], [[2, 3], [0, 0], [3, 2]]], [0, 0]], [[['.BW.', '.BW.', '.BW.', '.BW.'], [[2, 2], [1, 0]]], [0, 0]], [[['.....', '.BBB.', '.B.B.', '.BBB.', '.....'], [[1, 2], [3, 2], [4, 0]]], [0, 0]]], [[[['..B..', '..B..', 'BBBBB', 'WWWWW', '..W..'], [[3, 3]]], [8, 2]], [[['B.B.W', '.B.W.', 'B.BW.', 'BBW.W', '..W..'], []], [3, 5]], [[['W....', '.....', '.....', '.....', '....B'], [[0, 4]]], [0, 0]], [[['.W.B.', 'W.WB.', '.WB..', 'WB...', 'B....'], [[1, 2], [2, 0]]], [11, 1]], [[['BBBB', 'B..B', 'B..B', 'BBBB'], []], [4, 0]], [[['WWW', 'W.W', 'WWW'], [[0, 2]]], [0, 1]], [[['..W', '.W.', 'W..'], [[0, 2]]], [0, 0]], [[['B.BWW', '.BW..', 'WBWWW', '.BBBW'], [[1, 3]]], [1, 0]]]]
for i, (args, expected) in enumerate(fixtures[N-1]):
check("seki territory 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 |
|---|---|---|---|
| seki territory case 0 | [8, 8] | [0, 8] | Failed |
| seki territory case 1 | [0, 0] | [0, 0] | Passed |
| seki territory case 2 | [0, 8] | [0, 8] | Passed |
| seki territory case 3 | [0, 0] | [0, 0] | Passed |
| seki territory case 4 | [0, 0] | [0, 0] | Passed |
| seki territory case 5 | [0, 6] | [0, 0] | Failed |
| seki territory case 6 | [0, 0] | [0, 0] | Passed |
| seki territory case 7 | [4, 0] | [0, 0] | Failed |
SHA-256 / 8fc0b2aba1081560eb86118b08caaa7ecd7f4100fb8f16d1d8d51601cc2a56dd
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(x):
board, seki = x
n = len(board)
m = len(board[0])
sk = {tuple(p) for p in seki}
tb = 0
tw = 0
seen = set()
for r in range(n):
for c in range(m):
if board[r][c] != '.' or (r, c) in seen:
continue
seen.add((r, c))
stack = [(r, c)]
size = 0
cols = set()
frozen = False
while stack:
i, j = stack.pop()
size += 1
if (i, j) in sk:
frozen = True
for p, q in ((i, j + 1), (i + 1, j), (i, j - 1), (i - 1, j)):
if not (0 <= p < n and 0 <= q < m):
continue
if board[p][q] == '.':
if (p, q) not in seen:
seen.add((p, q))
stack.append((p, q))
else:
cols.add(board[p][q])
if (p, q) in sk and (i, j) == (r, c):
frozen = True
if frozen or len(cols) != 1:
continue
if 'B' in cols:
tb += size
else:
tw += size
return [tb, tw]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[[[['..BW..', '..BW..', '..BW..', '..BW..'], [[1, 2], [3, 2], [3, 0]]], [0, 8]], [[['....BW', '....BW', '....BW', '....BW', '....BW', '...WBW', 'W...BW'], []], [0, 0]], [[['...BW..', '.W.BW..', '...BW..', '..WBW..'], [[1, 1]]], [0, 8]], [[['...BW.', 'W..BW.', '...BWB', '.W.BW.', '...BW.'], [[4, 3]]], [0, 0]], [[['....BW', '....BW', '.W..BW', '....BW', '....BW'], [[1, 5], [2, 1]]], [0, 0]], [[['WBW.', '.BW.', 'WBW.', '.BW.', '.BW.', '.BW.'], [[2, 0], [4, 3]]], [0, 0]], [[['.WBW', '..BW', '.WBW', '..BW'], [[2, 3], [2, 0]]], [0, 0]], [[['..B.', '.B..', '.BB.'], [[0, 2]]], [0, 0]]], [[[['.....BW', '.....BW', '.....BW', '.....BW', '.....BW', '.W...BW'], [[4, 6], [2, 6]]], [0, 0]], [[['..BWB', 'W.BW.', '..BW.', '..BW.'], [[3, 2]]], [0, 0]], [[['.W.BWB', '...BW.', '...BW.', '...BW.'], [[2, 4], [0, 5]]], [0, 0]], [[['.BW.B.', '.BW...', '.BW...', '.BW...'], [[1, 1], [0, 4], [3, 3]]], [0, 0]], [[['.WBW.', '..BW.', '..BW.', '..BW.'], []], [0, 4]], [[['....BW', '.W.WBW', '....BW', 'WW.WBW', '..W.BW', '.W..BW', '....BW'], [[2, 5], [1, 2]]], [0, 0]], [[['..BW.', '..BW.', '..BW.', '..BW.', '.WBW.'], [[0, 0]]], [0, 5]], [[['.BW.', '.BW.', '.BW.', '.BW.'], [[2, 2], [1, 0]]], [0, 0]]], [[[['..BWB.', '..BW..', '..BW..', '..BW..', '..BW..'], [[2, 2]]], [0, 0]], [[['.BW.', '.BW.', '.BW.', '.BW.'], [[0, 2], [3, 1], [0, 0]]], [0, 0]], [[['WW.BW.', '...BWB', '...BW.', '.W.BW.'], [[1, 5]]], [0, 0]], [[['..BW.', '..BW.', '..BW.', 'W.BWB', '..BWB', '..BW.', 'W.BW.'], [[3, 3], [0, 1]]], [0, 0]], [[['..BW..', '..BW..', '..BW..', '..BW..', '..BW..', '.WBW..'], [[2, 3]]], [0, 0]], [[['..BW.', '..BW.', '..BW.', 'WWBW.', '.WBW.'], []], [0, 6]], [[['.BW.', '.BWB', '.BW.', '.BWB', '.BW.'], [[4, 3]]], [5, 0]], [[['WBW..', '.BW..', '.BW..', '.BW..', '.BW.B', '.BW..'], [[4, 1]]], [0, 0]]], [[[['.BW..', '.BW..', '.BW..', '.BW..'], [[1, 1], [0, 2], [3, 3]]], [0, 0]], [[['..BW.', '..BW.', '..BWB', '..BW.', 'W.BW.', '..BW.', '..BW.'], [[2, 3], [2, 4], [6, 1]]], [0, 0]], [[['....', '....', '....', '....'], [[0, 0]]], [0, 0]], [[['...', '...', '...'], []], [0, 0]], [[['.B.', 'B.B', '.B.'], [[1, 1]]], [4, 0]], [[['B..W', 'B..W', 'B..W', 'B..W'], [[2, 3], [0, 0], [3, 2]]], [0, 0]], [[['.BW.', '.BW.', '.BW.', '.BW.'], [[2, 2], [1, 0]]], [0, 0]], [[['.....', '.BBB.', '.B.B.', '.BBB.', '.....'], [[1, 2], [3, 2], [4, 0]]], [0, 0]]], [[[['..B..', '..B..', 'BBBBB', 'WWWWW', '..W..'], [[3, 3]]], [8, 2]], [[['B.B.W', '.B.W.', 'B.BW.', 'BBW.W', '..W..'], []], [3, 5]], [[['W....', '.....', '.....', '.....', '....B'], [[0, 4]]], [0, 0]], [[['.W.B.', 'W.WB.', '.WB..', 'WB...', 'B....'], [[1, 2], [2, 0]]], [11, 1]], [[['BBBB', 'B..B', 'B..B', 'BBBB'], []], [4, 0]], [[['WWW', 'W.W', 'WWW'], [[0, 2]]], [0, 1]], [[['..W', '.W.', 'W..'], [[0, 2]]], [0, 0]], [[['B.BWW', '.BW..', 'WBWWW', '.BBBW'], [[1, 3]]], [1, 0]]]]
for i, (args, expected) in enumerate(fixtures[N-1]):
check("seki territory 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 |
|---|---|---|---|
| seki territory case 0 | [0, 8] | [0, 8] | Passed |
| seki territory case 1 | [0, 0] | [0, 0] | Passed |
| seki territory case 2 | [0, 8] | [0, 8] | Passed |
| seki territory case 3 | [0, 0] | [0, 0] | Passed |
| seki territory case 4 | [0, 0] | [0, 0] | Passed |
| seki territory case 5 | [0, 0] | [0, 0] | Passed |
| seki territory case 6 | [0, 0] | [0, 0] | Passed |
| seki territory case 7 | [4, 0] | [0, 0] | Failed |
SHA-256 / f349e6209c4d18acf3f37657545b2e877520c797da4c838dabb8fbcbfb92f964
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(x):
board, seki = x
n = len(board)
m = len(board[0])
sk = {tuple(p) for p in seki}
tb = 0
tw = 0
seen = set()
for r in range(n):
for c in range(m):
if board[r][c] != '.' or (r, c) in seen:
continue
seen.add((r, c))
stack = [(r, c)]
size = 0
cols = set()
frozen = False
while stack:
i, j = stack.pop()
size += 1
if (i, j) in sk:
frozen = True
for p, q in ((i, j + 1), (i + 1, j), (i, j - 1), (i - 1, j)):
if not (0 <= p < n and 0 <= q < m):
continue
if board[p][q] == '.':
if (p, q) not in seen:
seen.add((p, q))
stack.append((p, q))
else:
cols.add(board[p][q])
if (p, q) in sk:
frozen = True
if frozen or len(cols) != 1:
continue
if 'B' in cols:
tb += size
else:
tw += size
return [tb, tw]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[[[['..BW..', '..BW..', '..BW..', '..BW..'], [[1, 2], [3, 2], [3, 0]]], [0, 8]], [[['....BW', '....BW', '....BW', '....BW', '....BW', '...WBW', 'W...BW'], []], [0, 0]], [[['...BW..', '.W.BW..', '...BW..', '..WBW..'], [[1, 1]]], [0, 8]], [[['...BW.', 'W..BW.', '...BWB', '.W.BW.', '...BW.'], [[4, 3]]], [0, 0]], [[['....BW', '....BW', '.W..BW', '....BW', '....BW'], [[1, 5], [2, 1]]], [0, 0]], [[['WBW.', '.BW.', 'WBW.', '.BW.', '.BW.', '.BW.'], [[2, 0], [4, 3]]], [0, 0]], [[['.WBW', '..BW', '.WBW', '..BW'], [[2, 3], [2, 0]]], [0, 0]], [[['..B.', '.B..', '.BB.'], [[0, 2]]], [0, 0]]], [[[['.....BW', '.....BW', '.....BW', '.....BW', '.....BW', '.W...BW'], [[4, 6], [2, 6]]], [0, 0]], [[['..BWB', 'W.BW.', '..BW.', '..BW.'], [[3, 2]]], [0, 0]], [[['.W.BWB', '...BW.', '...BW.', '...BW.'], [[2, 4], [0, 5]]], [0, 0]], [[['.BW.B.', '.BW...', '.BW...', '.BW...'], [[1, 1], [0, 4], [3, 3]]], [0, 0]], [[['.WBW.', '..BW.', '..BW.', '..BW.'], []], [0, 4]], [[['....BW', '.W.WBW', '....BW', 'WW.WBW', '..W.BW', '.W..BW', '....BW'], [[2, 5], [1, 2]]], [0, 0]], [[['..BW.', '..BW.', '..BW.', '..BW.', '.WBW.'], [[0, 0]]], [0, 5]], [[['.BW.', '.BW.', '.BW.', '.BW.'], [[2, 2], [1, 0]]], [0, 0]]], [[[['..BWB.', '..BW..', '..BW..', '..BW..', '..BW..'], [[2, 2]]], [0, 0]], [[['.BW.', '.BW.', '.BW.', '.BW.'], [[0, 2], [3, 1], [0, 0]]], [0, 0]], [[['WW.BW.', '...BWB', '...BW.', '.W.BW.'], [[1, 5]]], [0, 0]], [[['..BW.', '..BW.', '..BW.', 'W.BWB', '..BWB', '..BW.', 'W.BW.'], [[3, 3], [0, 1]]], [0, 0]], [[['..BW..', '..BW..', '..BW..', '..BW..', '..BW..', '.WBW..'], [[2, 3]]], [0, 0]], [[['..BW.', '..BW.', '..BW.', 'WWBW.', '.WBW.'], []], [0, 6]], [[['.BW.', '.BWB', '.BW.', '.BWB', '.BW.'], [[4, 3]]], [5, 0]], [[['WBW..', '.BW..', '.BW..', '.BW..', '.BW.B', '.BW..'], [[4, 1]]], [0, 0]]], [[[['.BW..', '.BW..', '.BW..', '.BW..'], [[1, 1], [0, 2], [3, 3]]], [0, 0]], [[['..BW.', '..BW.', '..BWB', '..BW.', 'W.BW.', '..BW.', '..BW.'], [[2, 3], [2, 4], [6, 1]]], [0, 0]], [[['....', '....', '....', '....'], [[0, 0]]], [0, 0]], [[['...', '...', '...'], []], [0, 0]], [[['.B.', 'B.B', '.B.'], [[1, 1]]], [4, 0]], [[['B..W', 'B..W', 'B..W', 'B..W'], [[2, 3], [0, 0], [3, 2]]], [0, 0]], [[['.BW.', '.BW.', '.BW.', '.BW.'], [[2, 2], [1, 0]]], [0, 0]], [[['.....', '.BBB.', '.B.B.', '.BBB.', '.....'], [[1, 2], [3, 2], [4, 0]]], [0, 0]]], [[[['..B..', '..B..', 'BBBBB', 'WWWWW', '..W..'], [[3, 3]]], [8, 2]], [[['B.B.W', '.B.W.', 'B.BW.', 'BBW.W', '..W..'], []], [3, 5]], [[['W....', '.....', '.....', '.....', '....B'], [[0, 4]]], [0, 0]], [[['.W.B.', 'W.WB.', '.WB..', 'WB...', 'B....'], [[1, 2], [2, 0]]], [11, 1]], [[['BBBB', 'B..B', 'B..B', 'BBBB'], []], [4, 0]], [[['WWW', 'W.W', 'WWW'], [[0, 2]]], [0, 1]], [[['..W', '.W.', 'W..'], [[0, 2]]], [0, 0]], [[['B.BWW', '.BW..', 'WBWWW', '.BBBW'], [[1, 3]]], [1, 0]]]]
for i, (args, expected) in enumerate(fixtures[N-1]):
check("seki territory 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 |
|---|---|---|---|
| seki territory case 0 | [0, 8] | [0, 8] | Passed |
| seki territory case 1 | [0, 0] | [0, 0] | Passed |
| seki territory case 2 | [0, 8] | [0, 8] | Passed |
| seki territory case 3 | [0, 0] | [0, 0] | Passed |
| seki territory case 4 | [0, 0] | [0, 0] | Passed |
| seki territory case 5 | [0, 0] | [0, 0] | Passed |
| seki territory case 6 | [0, 0] | [0, 0] | Passed |
| seki territory case 7 | [0, 0] | [0, 0] | Passed |
SHA-256 / 1272bde1b9e00ab361300f9bf0700ee806284462273544310e99467779961fa0
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:18.812371+00:00.
Case digest / 95f98bb00d6b87707d2c46471361d2be860663a6fb14283a6db7799725f2102b