FA-82866 / Go territory scoring / Open access
Dead stones are credited as prisoners to their own colour · case 01
Marking a white group dead raises white prisoner count instead of black.
ROOT CAUSE
The removal loop increments the prisoner counter of the stone colour rather than the opponent.
VERIFIED REPAIR
A dead black stone is a white prisoner and a dead white stone is a black prisoner.
Unsuccessful approach: Using a bare else for white stones credits black a prisoner for duplicate or empty dead marks.
Case contract
Input [board, dead_points, prisoners_held_by_black, prisoners_held_by_white, komi_tenths]. Each listed dead stone is removed once and becomes a prisoner of its opponent (duplicates and empty points are ignored). Territory = empty regions (after removal) bordered by one colour only. Return [terr_b, terr_w, pris_b, pris_w, result] with result "B+x.y", "W+x.y" or "Jigo".
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, dead, capb, capw, komi = x
g = [list(row) for row in board]
pb = capb
pw = capw
for r, c in dead:
if g[r][c] == 'B':
pb += 1
elif g[r][c] == 'W':
pw += 1
g[r][c] = '.'
n = len(g)
m = len(g[0])
tb = 0
tw = 0
seen = set()
for r in range(n):
for c in range(m):
if g[r][c] != '.' or (r, c) in seen:
continue
stack = [(r, c)]
seen.add((r, c))
size = 0
owners = set()
while stack:
i, j = stack.pop()
size += 1
for p, q in ((i + 1, j), (i - 1, j), (i, j + 1), (i, j - 1)):
if 0 <= p < n and 0 <= q < m:
if g[p][q] == '.':
if (p, q) not in seen:
seen.add((p, q))
stack.append((p, q))
else:
owners.add(g[p][q])
if owners == {'B'}:
tb += size
elif owners == {'W'}:
tw += size
sb = (tb + pb) * 10
sw = (tw + pw) * 10 + komi
if sb > sw:
res = 'B+%d.%d' % ((sb - sw) // 10, (sb - sw) % 10)
elif sw > sb:
res = 'W+%d.%d' % ((sw - sb) // 10, (sw - sb) % 10)
else:
res = 'Jigo'
return [tb, tw, pb, pw, res]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[[[['W...BW', '....BW', '....BW', '....BW'], [[1, 4], [1, 4]], 1, 0, 55], [0, 0, 1, 1, 'W+5.5']], [[['..WBW', '...BW', '...BW', 'W..BW'], [[0, 3], [3, 4], [3, 0]], 3, 0, 65], [0, 0, 5, 1, 'W+2.5']], [[['..BW.', '..BW.', '..BW.', '..BWB', '..BW.', '..BW.'], [[3, 2], [3, 2]], 1, 1, 0], [0, 0, 1, 2, 'W+1.0']], [[['.BW.B..', '.BW....', '.BW....', '.BW.B..', '.BW....', '.BW.B..', '.BW....'], [[4, 2], [2, 1], [6, 1]], 3, 0, 0], [0, 0, 4, 2, 'B+2.0']], [[['.....BW', '....WBW', '.W...BW', '..W..BW', '...W.BW'], [[4, 5]], 0, 0, 65], [0, 0, 0, 1, 'W+7.5']], [[['W..BW.', '..WBW.', 'W..BW.', '...BW.', '...BW.', '..WBW.'], [[1, 2], [5, 2], [0, 4]], 0, 3, 5], [0, 0, 3, 3, 'W+0.5']], [[['W.BW..', 'W.BW..', '..BW..', '.WBW..', '..BW..', '..BW..', '..BW..'], [[3, 2]], 3, 3, 0], [0, 14, 3, 4, 'W+15.0']], [[['W.BW..', '..BW..', '..BW..', '.WBW.B', 'W.BW..', '..BW..', '.WBW..'], [[1, 2], [3, 2], [5, 0]], 2, 0, 55], [0, 0, 2, 2, 'W+5.5']]], [[[['..BW..', '..BW.B', '..BW..', '..BW..', '..BW..', '..BW..'], [[3, 3], [2, 3]], 1, 2, 5], [12, 0, 3, 2, 'B+12.5']], [[['....BW.', '....BW.', '.W..BW.', '...WBW.', '...WBWB', '....BW.'], [[5, 1]], 4, 3, 55], [0, 0, 4, 3, 'W+4.5']], [[['...BW..', '...BWB.', '...BW..', '...BW..', '...BW..'], [[0, 3], [0, 3], [4, 2]], 0, 1, 5], [0, 0, 0, 2, 'W+2.5']], [[['..BW', '.WBW', '..BW', '..BW'], [[3, 2], [0, 3], [3, 2]], 0, 4, 60], [0, 0, 1, 5, 'W+10.0']], [[['....BWB', '....BW.', '....BW.', '....BWB'], [[2, 5]], 4, 1, 0], [16, 0, 5, 1, 'B+20.0']], [[['.BW.', '.BW.', '.BW.', '.BW.'], [[3, 1]], 1, 1, 60], [0, 4, 1, 2, 'W+11.0']], [[['..BW', '..BW', '..BW', '..BW', '..BW', '..BW', '..BW'], [[0, 2], [6, 2], [5, 3]], 1, 1, 0], [0, 0, 2, 3, 'W+1.0']], [[['.BW.', '.BW.', '.BW.', '.BW.', '.BWB', '.BWB', 'WBW.'], [[4, 1], [4, 1]], 0, 2, 0], [0, 0, 0, 3, 'W+3.0']]], [[[['.BW.B..', '.BW....', '.BW....', '.BW.B..', '.BW....', '.BW.B..', '.BW....'], [[4, 2], [2, 1], [6, 1]], 3, 0, 0], [0, 0, 4, 2, 'B+2.0']], [[['.BW.', '.BW.', '.BW.', '.BW.', '.BWB', '.BWB', 'WBW.'], [[4, 1], [4, 1]], 0, 2, 0], [0, 0, 0, 3, 'W+3.0']], [[['W.BW...', '.WBW...', '..BW..B', '..BW...', '.WBWB..', '..BW...'], [[4, 4], [4, 0]], 3, 1, 55], [0, 0, 3, 2, 'W+4.5']], [[['WBW.B..', '.BW.B..', '.BWBB..', 'WBW....', '.BW.B..', '.BW.B..', 'WBW....'], [[2, 2], [6, 2], [2, 2]], 0, 1, 5], [0, 0, 2, 1, 'B+0.5']], [[['..BW', '.WBW', '..BW', '..BW', '..BW', '..BW'], [[1, 3], [3, 3], [1, 3]], 4, 1, 55], [0, 0, 6, 1, 'W+0.5']], [[['.....BW', '.....BW', '.....BW', '.W...BW', '.....BW'], [[3, 5], [1, 5], [3, 6], [3, 5]], 0, 3, 5], [0, 0, 1, 5, 'W+4.5']], [[['..BW..', '..BW.B', '..BW..', '..BW.B', 'W.BW..', '..BW..', '..BW..'], [[2, 2], [2, 2]], 2, 1, 0], [0, 0, 2, 2, 'Jigo']], [[['W..BWB', '...BW.', '...BW.', '...BWB'], [[0, 5]], 4, 0, 5], [0, 0, 4, 1, 'B+2.5']]], [[[['W.BW..', 'W.BW..', '..BW..', '.WBW..', '..BW..', '..BW..', '..BW..'], [[3, 2]], 3, 3, 0], [0, 14, 3, 4, 'W+15.0']], [[['W...BW', '....BW', '....BW', '....BW', '....BW'], [[0, 0], [0, 4]], 0, 0, 5], [0, 0, 1, 1, 'W+0.5']], [[['..BWB', '..BWB', 'W.BW.', '..BW.', '..BW.'], [], 2, 4, 55], [0, 0, 2, 4, 'W+7.5']], [[['.BW..', 'WBWB.', '.BW..', 'WBW..', '.BW..'], [[2, 1], [3, 1]], 2, 2, 0], [0, 0, 2, 4, 'W+2.0']], [[['..BW...', '..BWB..', '.WBW...', '..BW.B.', 'W.BW...', '..BW...', '..BWBB.'], [[6, 2]], 2, 0, 65], [0, 0, 2, 1, 'W+5.5']], [[['.BW..', '.BW..', '.BW..', '.BW..', '.BWB.', '.BW..', 'WBW..'], [[0, 2], [0, 2]], 0, 2, 0], [0, 0, 1, 2, 'W+1.0']], [[['W..BW', '...BW', '...BW', '...BW', '...BW', '...BW', '...BW'], [], 2, 1, 65], [0, 0, 2, 1, 'W+5.5']], [[['B..W', 'B..W', 'B..W', 'B..W'], [[2, 0], [2, 3], [0, 3], [2, 0]], 4, 2, 5], [0, 0, 6, 3, 'B+2.5']]], [[[['....BWB', '....BW.', '....BW.', '....BWB'], [[2, 5]], 4, 1, 0], [16, 0, 5, 1, 'B+20.0']], [[['...BWBB', 'W..BW..', '..WBW..', '...BW..', '...BW.B', '...BWB.'], [[3, 4]], 2, 4, 5], [1, 0, 3, 4, 'W+0.5']], [[['.BW...', '.BWB..', '.BW...', '.BW...', '.BW...', '.BW...', '.BW.BB'], [[1, 1], [1, 1], [2, 4]], 4, 1, 60], [0, 0, 4, 2, 'W+4.0']], [[['...BW', '...BW', 'W..BW', '...BW', '.W.BW', '...BW', 'W..BW'], [], 1, 1, 0], [0, 0, 1, 1, 'Jigo']], [[['....BW.', 'W..WBW.', 'W...BW.', '..W.BW.', '....BW.', '....BW.'], [[3, 4], [4, 4], [1, 0], [2, 3]], 1, 3, 65], [0, 6, 2, 5, 'W+15.5']], [[['....', '....', '....', '....'], [], 4, 0, 60], [0, 0, 4, 0, 'W+2.0']], [[['...', '...', '...'], [], 3, 2, 65], [0, 0, 3, 2, 'W+5.5']], [[['B.B...', 'WB...B', '......', '......', '.B.B.B', 'BB....'], [[5, 1], [5, 0], [5, 1]], 2, 3, 5], [1, 0, 2, 5, 'W+2.5']]]]
for i, (args, expected) in enumerate(fixtures[N-1]):
check("territory score 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 |
|---|---|---|---|
| territory score case 0 | [0, 0, 2, 0, 'W+3.5'] | [0, 0, 1, 1, 'W+5.5'] | Failed |
| territory score case 1 | [0, 0, 4, 2, 'W+4.5'] | [0, 0, 5, 1, 'W+2.5'] | Failed |
| territory score case 2 | [0, 0, 2, 1, 'B+1.0'] | [0, 0, 1, 2, 'W+1.0'] | Failed |
| territory score case 3 | [0, 0, 5, 1, 'B+4.0'] | [0, 0, 4, 2, 'B+2.0'] | Failed |
| territory score case 4 | [0, 0, 1, 0, 'W+5.5'] | [0, 0, 0, 1, 'W+7.5'] | Failed |
| territory score case 5 | [0, 0, 0, 6, 'W+6.5'] | [0, 0, 3, 3, 'W+0.5'] | Failed |
| territory score case 6 | [0, 14, 4, 3, 'W+13.0'] | [0, 14, 3, 4, 'W+15.0'] | Failed |
| territory score case 7 | [0, 0, 4, 0, 'W+1.5'] | [0, 0, 2, 2, 'W+5.5'] | Failed |
SHA-256 / 5fe396ae4a71923b4e28df03dcf3f5228b4a051a6a5eb667408d5500c18f07c3
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(x):
board, dead, capb, capw, komi = x
g = [list(row) for row in board]
pb = capb
pw = capw
for r, c in dead:
if g[r][c] == 'B':
pw += 1
else:
pb += 1
g[r][c] = '.'
n = len(g)
m = len(g[0])
tb = 0
tw = 0
seen = set()
for r in range(n):
for c in range(m):
if g[r][c] != '.' or (r, c) in seen:
continue
stack = [(r, c)]
seen.add((r, c))
size = 0
owners = set()
while stack:
i, j = stack.pop()
size += 1
for p, q in ((i + 1, j), (i - 1, j), (i, j + 1), (i, j - 1)):
if 0 <= p < n and 0 <= q < m:
if g[p][q] == '.':
if (p, q) not in seen:
seen.add((p, q))
stack.append((p, q))
else:
owners.add(g[p][q])
if owners == {'B'}:
tb += size
elif owners == {'W'}:
tw += size
sb = (tb + pb) * 10
sw = (tw + pw) * 10 + komi
if sb > sw:
res = 'B+%d.%d' % ((sb - sw) // 10, (sb - sw) % 10)
elif sw > sb:
res = 'W+%d.%d' % ((sw - sb) // 10, (sw - sb) % 10)
else:
res = 'Jigo'
return [tb, tw, pb, pw, res]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[[[['W...BW', '....BW', '....BW', '....BW'], [[1, 4], [1, 4]], 1, 0, 55], [0, 0, 1, 1, 'W+5.5']], [[['..WBW', '...BW', '...BW', 'W..BW'], [[0, 3], [3, 4], [3, 0]], 3, 0, 65], [0, 0, 5, 1, 'W+2.5']], [[['..BW.', '..BW.', '..BW.', '..BWB', '..BW.', '..BW.'], [[3, 2], [3, 2]], 1, 1, 0], [0, 0, 1, 2, 'W+1.0']], [[['.BW.B..', '.BW....', '.BW....', '.BW.B..', '.BW....', '.BW.B..', '.BW....'], [[4, 2], [2, 1], [6, 1]], 3, 0, 0], [0, 0, 4, 2, 'B+2.0']], [[['.....BW', '....WBW', '.W...BW', '..W..BW', '...W.BW'], [[4, 5]], 0, 0, 65], [0, 0, 0, 1, 'W+7.5']], [[['W..BW.', '..WBW.', 'W..BW.', '...BW.', '...BW.', '..WBW.'], [[1, 2], [5, 2], [0, 4]], 0, 3, 5], [0, 0, 3, 3, 'W+0.5']], [[['W.BW..', 'W.BW..', '..BW..', '.WBW..', '..BW..', '..BW..', '..BW..'], [[3, 2]], 3, 3, 0], [0, 14, 3, 4, 'W+15.0']], [[['W.BW..', '..BW..', '..BW..', '.WBW.B', 'W.BW..', '..BW..', '.WBW..'], [[1, 2], [3, 2], [5, 0]], 2, 0, 55], [0, 0, 2, 2, 'W+5.5']]], [[[['..BW..', '..BW.B', '..BW..', '..BW..', '..BW..', '..BW..'], [[3, 3], [2, 3]], 1, 2, 5], [12, 0, 3, 2, 'B+12.5']], [[['....BW.', '....BW.', '.W..BW.', '...WBW.', '...WBWB', '....BW.'], [[5, 1]], 4, 3, 55], [0, 0, 4, 3, 'W+4.5']], [[['...BW..', '...BWB.', '...BW..', '...BW..', '...BW..'], [[0, 3], [0, 3], [4, 2]], 0, 1, 5], [0, 0, 0, 2, 'W+2.5']], [[['..BW', '.WBW', '..BW', '..BW'], [[3, 2], [0, 3], [3, 2]], 0, 4, 60], [0, 0, 1, 5, 'W+10.0']], [[['....BWB', '....BW.', '....BW.', '....BWB'], [[2, 5]], 4, 1, 0], [16, 0, 5, 1, 'B+20.0']], [[['.BW.', '.BW.', '.BW.', '.BW.'], [[3, 1]], 1, 1, 60], [0, 4, 1, 2, 'W+11.0']], [[['..BW', '..BW', '..BW', '..BW', '..BW', '..BW', '..BW'], [[0, 2], [6, 2], [5, 3]], 1, 1, 0], [0, 0, 2, 3, 'W+1.0']], [[['.BW.', '.BW.', '.BW.', '.BW.', '.BWB', '.BWB', 'WBW.'], [[4, 1], [4, 1]], 0, 2, 0], [0, 0, 0, 3, 'W+3.0']]], [[[['.BW.B..', '.BW....', '.BW....', '.BW.B..', '.BW....', '.BW.B..', '.BW....'], [[4, 2], [2, 1], [6, 1]], 3, 0, 0], [0, 0, 4, 2, 'B+2.0']], [[['.BW.', '.BW.', '.BW.', '.BW.', '.BWB', '.BWB', 'WBW.'], [[4, 1], [4, 1]], 0, 2, 0], [0, 0, 0, 3, 'W+3.0']], [[['W.BW...', '.WBW...', '..BW..B', '..BW...', '.WBWB..', '..BW...'], [[4, 4], [4, 0]], 3, 1, 55], [0, 0, 3, 2, 'W+4.5']], [[['WBW.B..', '.BW.B..', '.BWBB..', 'WBW....', '.BW.B..', '.BW.B..', 'WBW....'], [[2, 2], [6, 2], [2, 2]], 0, 1, 5], [0, 0, 2, 1, 'B+0.5']], [[['..BW', '.WBW', '..BW', '..BW', '..BW', '..BW'], [[1, 3], [3, 3], [1, 3]], 4, 1, 55], [0, 0, 6, 1, 'W+0.5']], [[['.....BW', '.....BW', '.....BW', '.W...BW', '.....BW'], [[3, 5], [1, 5], [3, 6], [3, 5]], 0, 3, 5], [0, 0, 1, 5, 'W+4.5']], [[['..BW..', '..BW.B', '..BW..', '..BW.B', 'W.BW..', '..BW..', '..BW..'], [[2, 2], [2, 2]], 2, 1, 0], [0, 0, 2, 2, 'Jigo']], [[['W..BWB', '...BW.', '...BW.', '...BWB'], [[0, 5]], 4, 0, 5], [0, 0, 4, 1, 'B+2.5']]], [[[['W.BW..', 'W.BW..', '..BW..', '.WBW..', '..BW..', '..BW..', '..BW..'], [[3, 2]], 3, 3, 0], [0, 14, 3, 4, 'W+15.0']], [[['W...BW', '....BW', '....BW', '....BW', '....BW'], [[0, 0], [0, 4]], 0, 0, 5], [0, 0, 1, 1, 'W+0.5']], [[['..BWB', '..BWB', 'W.BW.', '..BW.', '..BW.'], [], 2, 4, 55], [0, 0, 2, 4, 'W+7.5']], [[['.BW..', 'WBWB.', '.BW..', 'WBW..', '.BW..'], [[2, 1], [3, 1]], 2, 2, 0], [0, 0, 2, 4, 'W+2.0']], [[['..BW...', '..BWB..', '.WBW...', '..BW.B.', 'W.BW...', '..BW...', '..BWBB.'], [[6, 2]], 2, 0, 65], [0, 0, 2, 1, 'W+5.5']], [[['.BW..', '.BW..', '.BW..', '.BW..', '.BWB.', '.BW..', 'WBW..'], [[0, 2], [0, 2]], 0, 2, 0], [0, 0, 1, 2, 'W+1.0']], [[['W..BW', '...BW', '...BW', '...BW', '...BW', '...BW', '...BW'], [], 2, 1, 65], [0, 0, 2, 1, 'W+5.5']], [[['B..W', 'B..W', 'B..W', 'B..W'], [[2, 0], [2, 3], [0, 3], [2, 0]], 4, 2, 5], [0, 0, 6, 3, 'B+2.5']]], [[[['....BWB', '....BW.', '....BW.', '....BWB'], [[2, 5]], 4, 1, 0], [16, 0, 5, 1, 'B+20.0']], [[['...BWBB', 'W..BW..', '..WBW..', '...BW..', '...BW.B', '...BWB.'], [[3, 4]], 2, 4, 5], [1, 0, 3, 4, 'W+0.5']], [[['.BW...', '.BWB..', '.BW...', '.BW...', '.BW...', '.BW...', '.BW.BB'], [[1, 1], [1, 1], [2, 4]], 4, 1, 60], [0, 0, 4, 2, 'W+4.0']], [[['...BW', '...BW', 'W..BW', '...BW', '.W.BW', '...BW', 'W..BW'], [], 1, 1, 0], [0, 0, 1, 1, 'Jigo']], [[['....BW.', 'W..WBW.', 'W...BW.', '..W.BW.', '....BW.', '....BW.'], [[3, 4], [4, 4], [1, 0], [2, 3]], 1, 3, 65], [0, 6, 2, 5, 'W+15.5']], [[['....', '....', '....', '....'], [], 4, 0, 60], [0, 0, 4, 0, 'W+2.0']], [[['...', '...', '...'], [], 3, 2, 65], [0, 0, 3, 2, 'W+5.5']], [[['B.B...', 'WB...B', '......', '......', '.B.B.B', 'BB....'], [[5, 1], [5, 0], [5, 1]], 2, 3, 5], [1, 0, 2, 5, 'W+2.5']]]]
for i, (args, expected) in enumerate(fixtures[N-1]):
check("territory score 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 |
|---|---|---|---|
| territory score case 0 | [0, 0, 2, 1, 'W+4.5'] | [0, 0, 1, 1, 'W+5.5'] | Failed |
| territory score case 1 | [0, 0, 5, 1, 'W+2.5'] | [0, 0, 5, 1, 'W+2.5'] | Passed |
| territory score case 2 | [0, 0, 2, 2, 'Jigo'] | [0, 0, 1, 2, 'W+1.0'] | Failed |
| territory score case 3 | [0, 0, 4, 2, 'B+2.0'] | [0, 0, 4, 2, 'B+2.0'] | Passed |
| territory score case 4 | [0, 0, 0, 1, 'W+7.5'] | [0, 0, 0, 1, 'W+7.5'] | Passed |
| territory score case 5 | [0, 0, 3, 3, 'W+0.5'] | [0, 0, 3, 3, 'W+0.5'] | Passed |
| territory score case 6 | [0, 14, 3, 4, 'W+15.0'] | [0, 14, 3, 4, 'W+15.0'] | Passed |
| territory score case 7 | [0, 0, 3, 2, 'W+4.5'] | [0, 0, 2, 2, 'W+5.5'] | Failed |
SHA-256 / 48ebb5cdabf96dd14e30e36acaaf5347e24a85e21f24d7948c3376f82da77544
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(x):
board, dead, capb, capw, komi = x
g = [list(row) for row in board]
pb = capb
pw = capw
for r, c in dead:
if g[r][c] == 'B':
pw += 1
elif g[r][c] == 'W':
pb += 1
g[r][c] = '.'
n = len(g)
m = len(g[0])
tb = 0
tw = 0
seen = set()
for r in range(n):
for c in range(m):
if g[r][c] != '.' or (r, c) in seen:
continue
stack = [(r, c)]
seen.add((r, c))
size = 0
owners = set()
while stack:
i, j = stack.pop()
size += 1
for p, q in ((i + 1, j), (i - 1, j), (i, j + 1), (i, j - 1)):
if 0 <= p < n and 0 <= q < m:
if g[p][q] == '.':
if (p, q) not in seen:
seen.add((p, q))
stack.append((p, q))
else:
owners.add(g[p][q])
if owners == {'B'}:
tb += size
elif owners == {'W'}:
tw += size
sb = (tb + pb) * 10
sw = (tw + pw) * 10 + komi
if sb > sw:
res = 'B+%d.%d' % ((sb - sw) // 10, (sb - sw) % 10)
elif sw > sb:
res = 'W+%d.%d' % ((sw - sb) // 10, (sw - sb) % 10)
else:
res = 'Jigo'
return [tb, tw, pb, pw, res]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[[[['W...BW', '....BW', '....BW', '....BW'], [[1, 4], [1, 4]], 1, 0, 55], [0, 0, 1, 1, 'W+5.5']], [[['..WBW', '...BW', '...BW', 'W..BW'], [[0, 3], [3, 4], [3, 0]], 3, 0, 65], [0, 0, 5, 1, 'W+2.5']], [[['..BW.', '..BW.', '..BW.', '..BWB', '..BW.', '..BW.'], [[3, 2], [3, 2]], 1, 1, 0], [0, 0, 1, 2, 'W+1.0']], [[['.BW.B..', '.BW....', '.BW....', '.BW.B..', '.BW....', '.BW.B..', '.BW....'], [[4, 2], [2, 1], [6, 1]], 3, 0, 0], [0, 0, 4, 2, 'B+2.0']], [[['.....BW', '....WBW', '.W...BW', '..W..BW', '...W.BW'], [[4, 5]], 0, 0, 65], [0, 0, 0, 1, 'W+7.5']], [[['W..BW.', '..WBW.', 'W..BW.', '...BW.', '...BW.', '..WBW.'], [[1, 2], [5, 2], [0, 4]], 0, 3, 5], [0, 0, 3, 3, 'W+0.5']], [[['W.BW..', 'W.BW..', '..BW..', '.WBW..', '..BW..', '..BW..', '..BW..'], [[3, 2]], 3, 3, 0], [0, 14, 3, 4, 'W+15.0']], [[['W.BW..', '..BW..', '..BW..', '.WBW.B', 'W.BW..', '..BW..', '.WBW..'], [[1, 2], [3, 2], [5, 0]], 2, 0, 55], [0, 0, 2, 2, 'W+5.5']]], [[[['..BW..', '..BW.B', '..BW..', '..BW..', '..BW..', '..BW..'], [[3, 3], [2, 3]], 1, 2, 5], [12, 0, 3, 2, 'B+12.5']], [[['....BW.', '....BW.', '.W..BW.', '...WBW.', '...WBWB', '....BW.'], [[5, 1]], 4, 3, 55], [0, 0, 4, 3, 'W+4.5']], [[['...BW..', '...BWB.', '...BW..', '...BW..', '...BW..'], [[0, 3], [0, 3], [4, 2]], 0, 1, 5], [0, 0, 0, 2, 'W+2.5']], [[['..BW', '.WBW', '..BW', '..BW'], [[3, 2], [0, 3], [3, 2]], 0, 4, 60], [0, 0, 1, 5, 'W+10.0']], [[['....BWB', '....BW.', '....BW.', '....BWB'], [[2, 5]], 4, 1, 0], [16, 0, 5, 1, 'B+20.0']], [[['.BW.', '.BW.', '.BW.', '.BW.'], [[3, 1]], 1, 1, 60], [0, 4, 1, 2, 'W+11.0']], [[['..BW', '..BW', '..BW', '..BW', '..BW', '..BW', '..BW'], [[0, 2], [6, 2], [5, 3]], 1, 1, 0], [0, 0, 2, 3, 'W+1.0']], [[['.BW.', '.BW.', '.BW.', '.BW.', '.BWB', '.BWB', 'WBW.'], [[4, 1], [4, 1]], 0, 2, 0], [0, 0, 0, 3, 'W+3.0']]], [[[['.BW.B..', '.BW....', '.BW....', '.BW.B..', '.BW....', '.BW.B..', '.BW....'], [[4, 2], [2, 1], [6, 1]], 3, 0, 0], [0, 0, 4, 2, 'B+2.0']], [[['.BW.', '.BW.', '.BW.', '.BW.', '.BWB', '.BWB', 'WBW.'], [[4, 1], [4, 1]], 0, 2, 0], [0, 0, 0, 3, 'W+3.0']], [[['W.BW...', '.WBW...', '..BW..B', '..BW...', '.WBWB..', '..BW...'], [[4, 4], [4, 0]], 3, 1, 55], [0, 0, 3, 2, 'W+4.5']], [[['WBW.B..', '.BW.B..', '.BWBB..', 'WBW....', '.BW.B..', '.BW.B..', 'WBW....'], [[2, 2], [6, 2], [2, 2]], 0, 1, 5], [0, 0, 2, 1, 'B+0.5']], [[['..BW', '.WBW', '..BW', '..BW', '..BW', '..BW'], [[1, 3], [3, 3], [1, 3]], 4, 1, 55], [0, 0, 6, 1, 'W+0.5']], [[['.....BW', '.....BW', '.....BW', '.W...BW', '.....BW'], [[3, 5], [1, 5], [3, 6], [3, 5]], 0, 3, 5], [0, 0, 1, 5, 'W+4.5']], [[['..BW..', '..BW.B', '..BW..', '..BW.B', 'W.BW..', '..BW..', '..BW..'], [[2, 2], [2, 2]], 2, 1, 0], [0, 0, 2, 2, 'Jigo']], [[['W..BWB', '...BW.', '...BW.', '...BWB'], [[0, 5]], 4, 0, 5], [0, 0, 4, 1, 'B+2.5']]], [[[['W.BW..', 'W.BW..', '..BW..', '.WBW..', '..BW..', '..BW..', '..BW..'], [[3, 2]], 3, 3, 0], [0, 14, 3, 4, 'W+15.0']], [[['W...BW', '....BW', '....BW', '....BW', '....BW'], [[0, 0], [0, 4]], 0, 0, 5], [0, 0, 1, 1, 'W+0.5']], [[['..BWB', '..BWB', 'W.BW.', '..BW.', '..BW.'], [], 2, 4, 55], [0, 0, 2, 4, 'W+7.5']], [[['.BW..', 'WBWB.', '.BW..', 'WBW..', '.BW..'], [[2, 1], [3, 1]], 2, 2, 0], [0, 0, 2, 4, 'W+2.0']], [[['..BW...', '..BWB..', '.WBW...', '..BW.B.', 'W.BW...', '..BW...', '..BWBB.'], [[6, 2]], 2, 0, 65], [0, 0, 2, 1, 'W+5.5']], [[['.BW..', '.BW..', '.BW..', '.BW..', '.BWB.', '.BW..', 'WBW..'], [[0, 2], [0, 2]], 0, 2, 0], [0, 0, 1, 2, 'W+1.0']], [[['W..BW', '...BW', '...BW', '...BW', '...BW', '...BW', '...BW'], [], 2, 1, 65], [0, 0, 2, 1, 'W+5.5']], [[['B..W', 'B..W', 'B..W', 'B..W'], [[2, 0], [2, 3], [0, 3], [2, 0]], 4, 2, 5], [0, 0, 6, 3, 'B+2.5']]], [[[['....BWB', '....BW.', '....BW.', '....BWB'], [[2, 5]], 4, 1, 0], [16, 0, 5, 1, 'B+20.0']], [[['...BWBB', 'W..BW..', '..WBW..', '...BW..', '...BW.B', '...BWB.'], [[3, 4]], 2, 4, 5], [1, 0, 3, 4, 'W+0.5']], [[['.BW...', '.BWB..', '.BW...', '.BW...', '.BW...', '.BW...', '.BW.BB'], [[1, 1], [1, 1], [2, 4]], 4, 1, 60], [0, 0, 4, 2, 'W+4.0']], [[['...BW', '...BW', 'W..BW', '...BW', '.W.BW', '...BW', 'W..BW'], [], 1, 1, 0], [0, 0, 1, 1, 'Jigo']], [[['....BW.', 'W..WBW.', 'W...BW.', '..W.BW.', '....BW.', '....BW.'], [[3, 4], [4, 4], [1, 0], [2, 3]], 1, 3, 65], [0, 6, 2, 5, 'W+15.5']], [[['....', '....', '....', '....'], [], 4, 0, 60], [0, 0, 4, 0, 'W+2.0']], [[['...', '...', '...'], [], 3, 2, 65], [0, 0, 3, 2, 'W+5.5']], [[['B.B...', 'WB...B', '......', '......', '.B.B.B', 'BB....'], [[5, 1], [5, 0], [5, 1]], 2, 3, 5], [1, 0, 2, 5, 'W+2.5']]]]
for i, (args, expected) in enumerate(fixtures[N-1]):
check("territory score 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 |
|---|---|---|---|
| territory score case 0 | [0, 0, 1, 1, 'W+5.5'] | [0, 0, 1, 1, 'W+5.5'] | Passed |
| territory score case 1 | [0, 0, 5, 1, 'W+2.5'] | [0, 0, 5, 1, 'W+2.5'] | Passed |
| territory score case 2 | [0, 0, 1, 2, 'W+1.0'] | [0, 0, 1, 2, 'W+1.0'] | Passed |
| territory score case 3 | [0, 0, 4, 2, 'B+2.0'] | [0, 0, 4, 2, 'B+2.0'] | Passed |
| territory score case 4 | [0, 0, 0, 1, 'W+7.5'] | [0, 0, 0, 1, 'W+7.5'] | Passed |
| territory score case 5 | [0, 0, 3, 3, 'W+0.5'] | [0, 0, 3, 3, 'W+0.5'] | Passed |
| territory score case 6 | [0, 14, 3, 4, 'W+15.0'] | [0, 14, 3, 4, 'W+15.0'] | Passed |
| territory score case 7 | [0, 0, 2, 2, 'W+5.5'] | [0, 0, 2, 2, 'W+5.5'] | Passed |
SHA-256 / 0365910bb99af659ecf629350e63a54b8cceba7fe105653806236b75b95e6a96
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:16.016132+00:00.
Case digest / 9071c2e0cfb2ab4206eaf5c3986f5938fc74a2d434564adef373e74e9773a57c