FA-83156 / Go territory scoring / Open access
Eyes inside seki are counted as territory · case 01
Japanese scoring credits eye points of seki groups.
ROOT CAUSE
The region filter only checks the number of bordering colours.
VERIFIED REPAIR
Skip any frozen region.
Unsuccessful approach: Excluding only single-point frozen regions still counts larger seki eye spaces.
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()
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 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]], [[['..BW..', '..BW..', '..BW..', '..BW..', '..BW..', '.WBW..'], [[2, 3]]], [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]], [[['..W', '.W.', 'W..'], [[0, 2]]], [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]], [[['BBBB', 'B..B', 'BBBB'], [[1, 1]]], [0, 0]]], [[[['.BW.B.', '.BW...', '.BW...', '.BW...'], [[1, 1], [0, 4], [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]], [[['..B..', '..B..', 'BBBBB', 'WWWWW', '..W..'], [[3, 3]]], [8, 2]]], [[[['..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]], [[['B.W', '...', 'W.B'], []], [0, 0]], [[['BW.', 'BW.', 'BW.'], [[2, 2]]], [0, 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 | [0, 12] | [0, 0] | Failed |
SHA-256 / 4f8f2f4a2ce7174f68d563290a8d7b976fb4240927f4935716938abd60db2cdb
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:
frozen = True
if frozen and size == 1 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]], [[['..BW..', '..BW..', '..BW..', '..BW..', '..BW..', '.WBW..'], [[2, 3]]], [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]], [[['..W', '.W.', 'W..'], [[0, 2]]], [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]], [[['BBBB', 'B..B', 'BBBB'], [[1, 1]]], [0, 0]]], [[[['.BW.B.', '.BW...', '.BW...', '.BW...'], [[1, 1], [0, 4], [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]], [[['..B..', '..B..', 'BBBBB', 'WWWWW', '..W..'], [[3, 3]]], [8, 2]]], [[[['..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]], [[['B.W', '...', 'W.B'], []], [0, 0]], [[['BW.', 'BW.', 'BW.'], [[2, 2]]], [0, 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 | [0, 12] | [0, 0] | Failed |
SHA-256 / 1d1aa1574ee5634bfbd1cc24778077a6fe5e4bca10890c6ebd74b5f5c7d4e1e1
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]], [[['..BW..', '..BW..', '..BW..', '..BW..', '..BW..', '.WBW..'], [[2, 3]]], [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]], [[['..W', '.W.', 'W..'], [[0, 2]]], [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]], [[['BBBB', 'B..B', 'BBBB'], [[1, 1]]], [0, 0]]], [[[['.BW.B.', '.BW...', '.BW...', '.BW...'], [[1, 1], [0, 4], [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]], [[['..B..', '..B..', 'BBBBB', 'WWWWW', '..W..'], [[3, 3]]], [8, 2]]], [[[['..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]], [[['B.W', '...', 'W.B'], []], [0, 0]], [[['BW.', 'BW.', 'BW.'], [[2, 2]]], [0, 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 / b22b67442ea91e79010c970a76047b84f49a2fca1a0237f435ec1ded69228f70
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.900999+00:00.
Case digest / af55324570ecb40d9f1958a52f08a576fa97459e0abd0e28448a8eefd7cdc9f4