FA-83196 / Go territory scoring / Open access
Dead stones are rendered as unknown points that neutralise territory · case 01
A dead invader turns the surrounding territory into dame.
ROOT CAUSE
Dead points are replaced with "?" rather than removed.
VERIFIED REPAIR
Replace dead stones with empty points before region analysis.
Unsuccessful approach: Removing them for analysis but rendering from the original board shows dead stones as alive.
Case contract
Input [board, dead_points]. Remove dead stones, then render each point: live stones as B/W, territory (region bordered by one colour) as lower-case b/w, other empty points as "?". Return 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):
board, dead = x
n = len(board)
m = len(board[0])
dd = {tuple(p) for p in dead}
g = [[('?' if (r, c) in dd else board[r][c]) for c in range(m)] for r in range(n)]
out = [[g[r][c] for c in range(m)] for r in range(n)]
seen = set()
for r in range(n):
for c in range(m):
if g[r][c] != '.' or (r, c) in seen:
continue
seen.add((r, c))
region = [(r, c)]
k = 0
cols = set()
while k < len(region):
i, j = region[k]
k += 1
for p, q in ((i - 1, j), (i, j - 1), (i + 1, j), (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))
region.append((p, q))
else:
cols.add(g[p][q])
mark = cols.pop().lower() if len(cols) == 1 else '?'
for i, j in region:
out[i][j] = mark
return [''.join(row) for row in out]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[[[['.BW.', '.BW.', '.BW.', '.BWB', '.BW.', '.BWB'], [[1, 1]]], ['?BW?', '??W?', '?BW?', '?BWB', '?BW?', '?BWB']], [[['...WBW.', '....BW.', '....BW.', '.W..BW.'], []], ['???WBWw', '????BWw', '????BWw', '?W??BWw']], [[['.BWB.', '.BW..', '.BW..', '.BWB.'], [[2, 2], [0, 2]]], ['bB?B?', 'bBW??', 'bB???', 'bBWB?']], [[['WBW...', '.BW...', '.BW..B', '.BW...', '.BW...'], [[0, 2]]], ['WB????', '?BW???', '?BW??B', '?BW???', '?BW???']], [[['.BW.B..', 'WBW....', '.BW....', '.BW....', '.BW....'], [[2, 2]]], ['?BW?B??', 'WBW????', '?B?????', '?BW????', '?BW????']], [[['....BW', '....BW', '....BW', '....BW', '....BW', '....BW'], [[2, 5], [2, 4]]], ['????BW', '????BW', '??????', '????BW', '????BW', '????BW']], [[['..BW', '..BW', '..BW', '..BW', '..BW', '..BW', '..BW'], [[3, 2]]], ['??BW', '??BW', '??BW', '???W', '??BW', '??BW', '??BW']], [[['.B.', 'B.B', '.B.'], [[1, 2], [2, 1]]], ['bBb', 'Bbb', 'bbb']]], [[[['W.BW.', '..BW.', '.WBW.', '.WBW.', '..BW.', '..BW.', '..BW.'], []], ['W?BWw', '??BWw', '?WBWw', '?WBWw', '??BWw', '??BWw', '??BWw']], [[['.W.W.BW', '.....BW', '.W...BW', '...W.BW', '.....BW'], [[2, 1]]], ['?W?W?BW', '?????BW', '?????BW', '???W?BW', '?????BW']], [[['.BWB', '.BW.', 'WBW.', '.BW.', '.BW.', 'WBW.'], [[4, 1]]], ['?BWB', '?BW?', 'WBW?', '?BW?', '??W?', 'WBW?']], [[['.BW.', '.BW.', 'WBW.', '.BW.', '.BW.'], [[0, 1], [3, 1]]], ['??Ww', '?BWw', 'WBWw', '??Ww', '?BWw']], [[['.W..BW', '....BW', 'W...BW', '....BW'], [[1, 4]]], ['?W??BW', '?????W', 'W???BW', '????BW']], [[['..BW', '..BW', 'W.BW', '..BW', '..BW'], [[4, 2], [3, 2]]], ['??BW', '??BW', 'W?BW', '???W', '???W']], [[['.BW...', '.BW...', '.BW...', 'WBW..B', '.BW..B', '.BW..B'], []], ['?BW???', '?BW???', '?BW???', 'WBW??B', '?BW??B', '?BW??B']], [[['BBBB', 'B..B', 'B..B', 'BBBB'], [[0, 2]]], ['BBbB', 'BbbB', 'BbbB', 'BBBB']]], [[[['.BW..', 'WBW..', 'WBWB.', '.BW..', '.BW..'], []], ['?BW??', 'WBW??', 'WBWB?', '?BW??', '?BW??']], [[['...BW', '...BW', '...BW', '...BW', 'W..BW', '.W.BW', '...BW'], [[2, 4], [3, 3]]], ['???BW', '???BW', '???B?', '????W', 'W??BW', '?W?BW', '???BW']], [[['...BW', '..WBW', '...BW', '...BW', '...BW'], []], ['???BW', '??WBW', '???BW', '???BW', '???BW']], [[['...BW', '...BW', '...BW', 'W..BW'], []], ['???BW', '???BW', '???BW', 'W??BW']], [[['..BW.', '..BW.', '..BWB', '..BW.', '..BW.', '..BW.', '..BW.'], [[2, 2], [3, 3]]], ['??BW?', '??BW?', '???WB', '??B??', '??BW?', '??BW?', '??BW?']], [[['.BW..', '.BW.B', '.BWB.', '.BW..', '.BW.B', '.BW..', 'WBW..'], [[4, 1]]], ['?BW??', '?BW?B', '?BWB?', '?BW??', '??W?B', '?BW??', 'WBW??']], [[['..BW', 'W.BW', '..BW', '..BW', '..BW', 'W.BW'], [[0, 2], [5, 3]]], ['???W', 'W?BW', '??BW', '??BW', '??BW', 'W?B?']], [[['..W', '.W.', 'W..'], [[0, 2], [2, 0]]], ['www', 'wWw', 'www']]], [[[['...BW.', '...BW.', '...BW.', '...BW.', '...BW.', '...BW.'], [[2, 4]]], ['bbbBW?', 'bbbBW?', 'bbbB??', 'bbbBW?', 'bbbBW?', 'bbbBW?']], [[['...BW', '...BW', 'W..BW', 'W.WBW', '...BW', '...BW'], []], ['???BW', '???BW', 'W??BW', 'W?WBW', '???BW', '???BW']], [[['....', '....', '....', '....'], []], ['????', '????', '????', '????']], [[['...', '...', '...'], []], ['???', '???', '???']], [[['.B.', 'B.B', '.B.'], [[1, 2], [2, 1]]], ['bBb', 'Bbb', 'bbb']], [[['B..W', 'B..W', 'B..W', 'B..W'], [[2, 3]]], ['B??W', 'B??W', 'B???', 'B??W']], [[['.BW.', '.BW.', '.BW.', '.BW.'], [[0, 2]]], ['bB??', 'bBW?', 'bBW?', 'bBW?']], [[['..B.', '....', '....', '....', 'B...'], [[0, 2]]], ['bbbb', 'bbbb', 'bbbb', 'bbbb', 'Bbbb']]], [[[['.B.', 'B.B', '.B.'], [[1, 2], [2, 1]]], ['bBb', 'Bbb', 'bbb']], [[['B.B.W', '.B.W.', 'B.BW.', 'BBW.W', '..W..'], []], ['BbB?W', 'bB?Ww', 'BbBWw', 'BBWwW', '??Www']], [[['W....', '.....', '.....', '.....', '....B'], [[4, 4]]], ['Wwwww', 'wwwww', 'wwwww', 'wwwww', 'wwwww']], [[['.W.B.', 'W.WB.', '.WB..', 'WB...', 'B....'], [[3, 1], [3, 0]]], ['wW?B?', 'WwWB?', '?WB??', '?????', 'B????']], [[['BBBB', 'B..B', 'B..B', 'BBBB'], [[0, 2]]], ['BBbB', 'BbbB', 'BbbB', 'BBBB']], [[['WWW', 'W.W', 'WWW'], []], ['WWW', 'WwW', 'WWW']], [[['B.W', '...', 'W.B'], [[2, 2], [0, 0]]], ['wwW', 'www', 'Www']], [[['.B...', 'B....', '.....', '....W', '...W.'], [[1, 0]]], ['?B???', '?????', '?????', '????W', '???Ww']]]]
for i, (args, expected) in enumerate(fixtures[N-1]):
check("ownership map 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 |
|---|---|---|---|
| ownership map case 0 | ['?BW?', '??W?', '?BW?', '?BWB', '?BW?', '?BWB'] | ['?BW?', '??W?', '?BW?', '?BWB', '?BW?', '?BWB'] | Passed |
| ownership map case 1 | ['???WBWw', '????BWw', '????BWw', '?W??BWw'] | ['???WBWw', '????BWw', '????BWw', '?W??BWw'] | Passed |
| ownership map case 2 | ['bB?B?', 'bBW??', 'bB???', 'bBWB?'] | ['bB?B?', 'bBW??', 'bB???', 'bBWB?'] | Passed |
| ownership map case 3 | ['WB????', '?BW???', '?BW??B', '?BW???', '?BW???'] | ['WB????', '?BW???', '?BW??B', '?BW???', '?BW???'] | Passed |
| ownership map case 4 | ['?BW?B??', 'WBW????', '?B?????', '?BW????', '?BW????'] | ['?BW?B??', 'WBW????', '?B?????', '?BW????', '?BW????'] | Passed |
| ownership map case 5 | ['????BW', '????BW', '??????', '????BW', '????BW', '????BW'] | ['????BW', '????BW', '??????', '????BW', '????BW', '????BW'] | Passed |
| ownership map case 6 | ['??BW', '??BW', '??BW', '???W', '??BW', '??BW', '??BW'] | ['??BW', '??BW', '??BW', '???W', '??BW', '??BW', '??BW'] | Passed |
| ownership map case 7 | ['bB?', 'B??', '???'] | ['bBb', 'Bbb', 'bbb'] | Failed |
SHA-256 / e560fe25eb772b170ea3b769b85c2797dc353d170e6fd35f678454b6f6caa751
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(x):
board, dead = x
n = len(board)
m = len(board[0])
dd = {tuple(p) for p in dead}
g = [[('.' if (r, c) in dd else board[r][c]) for c in range(m)] for r in range(n)]
out = [[board[r][c] for c in range(m)] for r in range(n)]
seen = set()
for r in range(n):
for c in range(m):
if g[r][c] != '.' or (r, c) in seen:
continue
seen.add((r, c))
region = [(r, c)]
k = 0
cols = set()
while k < len(region):
i, j = region[k]
k += 1
for p, q in ((i - 1, j), (i, j - 1), (i + 1, j), (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))
region.append((p, q))
else:
cols.add(g[p][q])
mark = cols.pop().lower() if len(cols) == 1 else '?'
for i, j in region:
if board[i][j] == '.':
out[i][j] = mark
return [''.join(row) for row in out]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[[[['.BW.', '.BW.', '.BW.', '.BWB', '.BW.', '.BWB'], [[1, 1]]], ['?BW?', '??W?', '?BW?', '?BWB', '?BW?', '?BWB']], [[['...WBW.', '....BW.', '....BW.', '.W..BW.'], []], ['???WBWw', '????BWw', '????BWw', '?W??BWw']], [[['.BWB.', '.BW..', '.BW..', '.BWB.'], [[2, 2], [0, 2]]], ['bB?B?', 'bBW??', 'bB???', 'bBWB?']], [[['WBW...', '.BW...', '.BW..B', '.BW...', '.BW...'], [[0, 2]]], ['WB????', '?BW???', '?BW??B', '?BW???', '?BW???']], [[['.BW.B..', 'WBW....', '.BW....', '.BW....', '.BW....'], [[2, 2]]], ['?BW?B??', 'WBW????', '?B?????', '?BW????', '?BW????']], [[['....BW', '....BW', '....BW', '....BW', '....BW', '....BW'], [[2, 5], [2, 4]]], ['????BW', '????BW', '??????', '????BW', '????BW', '????BW']], [[['..BW', '..BW', '..BW', '..BW', '..BW', '..BW', '..BW'], [[3, 2]]], ['??BW', '??BW', '??BW', '???W', '??BW', '??BW', '??BW']], [[['.B.', 'B.B', '.B.'], [[1, 2], [2, 1]]], ['bBb', 'Bbb', 'bbb']]], [[[['W.BW.', '..BW.', '.WBW.', '.WBW.', '..BW.', '..BW.', '..BW.'], []], ['W?BWw', '??BWw', '?WBWw', '?WBWw', '??BWw', '??BWw', '??BWw']], [[['.W.W.BW', '.....BW', '.W...BW', '...W.BW', '.....BW'], [[2, 1]]], ['?W?W?BW', '?????BW', '?????BW', '???W?BW', '?????BW']], [[['.BWB', '.BW.', 'WBW.', '.BW.', '.BW.', 'WBW.'], [[4, 1]]], ['?BWB', '?BW?', 'WBW?', '?BW?', '??W?', 'WBW?']], [[['.BW.', '.BW.', 'WBW.', '.BW.', '.BW.'], [[0, 1], [3, 1]]], ['??Ww', '?BWw', 'WBWw', '??Ww', '?BWw']], [[['.W..BW', '....BW', 'W...BW', '....BW'], [[1, 4]]], ['?W??BW', '?????W', 'W???BW', '????BW']], [[['..BW', '..BW', 'W.BW', '..BW', '..BW'], [[4, 2], [3, 2]]], ['??BW', '??BW', 'W?BW', '???W', '???W']], [[['.BW...', '.BW...', '.BW...', 'WBW..B', '.BW..B', '.BW..B'], []], ['?BW???', '?BW???', '?BW???', 'WBW??B', '?BW??B', '?BW??B']], [[['BBBB', 'B..B', 'B..B', 'BBBB'], [[0, 2]]], ['BBbB', 'BbbB', 'BbbB', 'BBBB']]], [[[['.BW..', 'WBW..', 'WBWB.', '.BW..', '.BW..'], []], ['?BW??', 'WBW??', 'WBWB?', '?BW??', '?BW??']], [[['...BW', '...BW', '...BW', '...BW', 'W..BW', '.W.BW', '...BW'], [[2, 4], [3, 3]]], ['???BW', '???BW', '???B?', '????W', 'W??BW', '?W?BW', '???BW']], [[['...BW', '..WBW', '...BW', '...BW', '...BW'], []], ['???BW', '??WBW', '???BW', '???BW', '???BW']], [[['...BW', '...BW', '...BW', 'W..BW'], []], ['???BW', '???BW', '???BW', 'W??BW']], [[['..BW.', '..BW.', '..BWB', '..BW.', '..BW.', '..BW.', '..BW.'], [[2, 2], [3, 3]]], ['??BW?', '??BW?', '???WB', '??B??', '??BW?', '??BW?', '??BW?']], [[['.BW..', '.BW.B', '.BWB.', '.BW..', '.BW.B', '.BW..', 'WBW..'], [[4, 1]]], ['?BW??', '?BW?B', '?BWB?', '?BW??', '??W?B', '?BW??', 'WBW??']], [[['..BW', 'W.BW', '..BW', '..BW', '..BW', 'W.BW'], [[0, 2], [5, 3]]], ['???W', 'W?BW', '??BW', '??BW', '??BW', 'W?B?']], [[['..W', '.W.', 'W..'], [[0, 2], [2, 0]]], ['www', 'wWw', 'www']]], [[[['...BW.', '...BW.', '...BW.', '...BW.', '...BW.', '...BW.'], [[2, 4]]], ['bbbBW?', 'bbbBW?', 'bbbB??', 'bbbBW?', 'bbbBW?', 'bbbBW?']], [[['...BW', '...BW', 'W..BW', 'W.WBW', '...BW', '...BW'], []], ['???BW', '???BW', 'W??BW', 'W?WBW', '???BW', '???BW']], [[['....', '....', '....', '....'], []], ['????', '????', '????', '????']], [[['...', '...', '...'], []], ['???', '???', '???']], [[['.B.', 'B.B', '.B.'], [[1, 2], [2, 1]]], ['bBb', 'Bbb', 'bbb']], [[['B..W', 'B..W', 'B..W', 'B..W'], [[2, 3]]], ['B??W', 'B??W', 'B???', 'B??W']], [[['.BW.', '.BW.', '.BW.', '.BW.'], [[0, 2]]], ['bB??', 'bBW?', 'bBW?', 'bBW?']], [[['..B.', '....', '....', '....', 'B...'], [[0, 2]]], ['bbbb', 'bbbb', 'bbbb', 'bbbb', 'Bbbb']]], [[[['.B.', 'B.B', '.B.'], [[1, 2], [2, 1]]], ['bBb', 'Bbb', 'bbb']], [[['B.B.W', '.B.W.', 'B.BW.', 'BBW.W', '..W..'], []], ['BbB?W', 'bB?Ww', 'BbBWw', 'BBWwW', '??Www']], [[['W....', '.....', '.....', '.....', '....B'], [[4, 4]]], ['Wwwww', 'wwwww', 'wwwww', 'wwwww', 'wwwww']], [[['.W.B.', 'W.WB.', '.WB..', 'WB...', 'B....'], [[3, 1], [3, 0]]], ['wW?B?', 'WwWB?', '?WB??', '?????', 'B????']], [[['BBBB', 'B..B', 'B..B', 'BBBB'], [[0, 2]]], ['BBbB', 'BbbB', 'BbbB', 'BBBB']], [[['WWW', 'W.W', 'WWW'], []], ['WWW', 'WwW', 'WWW']], [[['B.W', '...', 'W.B'], [[2, 2], [0, 0]]], ['wwW', 'www', 'Www']], [[['.B...', 'B....', '.....', '....W', '...W.'], [[1, 0]]], ['?B???', '?????', '?????', '????W', '???Ww']]]]
for i, (args, expected) in enumerate(fixtures[N-1]):
check("ownership map 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 |
|---|---|---|---|
| ownership map case 0 | ['?BW?', '?BW?', '?BW?', '?BWB', '?BW?', '?BWB'] | ['?BW?', '??W?', '?BW?', '?BWB', '?BW?', '?BWB'] | Failed |
| ownership map case 1 | ['???WBWw', '????BWw', '????BWw', '?W??BWw'] | ['???WBWw', '????BWw', '????BWw', '?W??BWw'] | Passed |
| ownership map case 2 | ['bBWB?', 'bBW??', 'bBW??', 'bBWB?'] | ['bB?B?', 'bBW??', 'bB???', 'bBWB?'] | Failed |
| ownership map case 3 | ['WBW???', '?BW???', '?BW??B', '?BW???', '?BW???'] | ['WB????', '?BW???', '?BW??B', '?BW???', '?BW???'] | Failed |
| ownership map case 4 | ['?BW?B??', 'WBW????', '?BW????', '?BW????', '?BW????'] | ['?BW?B??', 'WBW????', '?B?????', '?BW????', '?BW????'] | Failed |
| ownership map case 5 | ['????BW', '????BW', '????BW', '????BW', '????BW', '????BW'] | ['????BW', '????BW', '??????', '????BW', '????BW', '????BW'] | Failed |
| ownership map case 6 | ['??BW', '??BW', '??BW', '??BW', '??BW', '??BW', '??BW'] | ['??BW', '??BW', '??BW', '???W', '??BW', '??BW', '??BW'] | Failed |
| ownership map case 7 | ['bBb', 'BbB', 'bBb'] | ['bBb', 'Bbb', 'bbb'] | Failed |
SHA-256 / 6dd54964082c6a449d7b1d2c98cbbbacbb100ae7fab5f5470064b67abc386b12
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(x):
board, dead = x
n = len(board)
m = len(board[0])
dd = {tuple(p) for p in dead}
g = [[('.' if (r, c) in dd else board[r][c]) for c in range(m)] for r in range(n)]
out = [[g[r][c] for c in range(m)] for r in range(n)]
seen = set()
for r in range(n):
for c in range(m):
if g[r][c] != '.' or (r, c) in seen:
continue
seen.add((r, c))
region = [(r, c)]
k = 0
cols = set()
while k < len(region):
i, j = region[k]
k += 1
for p, q in ((i - 1, j), (i, j - 1), (i + 1, j), (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))
region.append((p, q))
else:
cols.add(g[p][q])
mark = cols.pop().lower() if len(cols) == 1 else '?'
for i, j in region:
out[i][j] = mark
return [''.join(row) for row in out]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[[[['.BW.', '.BW.', '.BW.', '.BWB', '.BW.', '.BWB'], [[1, 1]]], ['?BW?', '??W?', '?BW?', '?BWB', '?BW?', '?BWB']], [[['...WBW.', '....BW.', '....BW.', '.W..BW.'], []], ['???WBWw', '????BWw', '????BWw', '?W??BWw']], [[['.BWB.', '.BW..', '.BW..', '.BWB.'], [[2, 2], [0, 2]]], ['bB?B?', 'bBW??', 'bB???', 'bBWB?']], [[['WBW...', '.BW...', '.BW..B', '.BW...', '.BW...'], [[0, 2]]], ['WB????', '?BW???', '?BW??B', '?BW???', '?BW???']], [[['.BW.B..', 'WBW....', '.BW....', '.BW....', '.BW....'], [[2, 2]]], ['?BW?B??', 'WBW????', '?B?????', '?BW????', '?BW????']], [[['....BW', '....BW', '....BW', '....BW', '....BW', '....BW'], [[2, 5], [2, 4]]], ['????BW', '????BW', '??????', '????BW', '????BW', '????BW']], [[['..BW', '..BW', '..BW', '..BW', '..BW', '..BW', '..BW'], [[3, 2]]], ['??BW', '??BW', '??BW', '???W', '??BW', '??BW', '??BW']], [[['.B.', 'B.B', '.B.'], [[1, 2], [2, 1]]], ['bBb', 'Bbb', 'bbb']]], [[[['W.BW.', '..BW.', '.WBW.', '.WBW.', '..BW.', '..BW.', '..BW.'], []], ['W?BWw', '??BWw', '?WBWw', '?WBWw', '??BWw', '??BWw', '??BWw']], [[['.W.W.BW', '.....BW', '.W...BW', '...W.BW', '.....BW'], [[2, 1]]], ['?W?W?BW', '?????BW', '?????BW', '???W?BW', '?????BW']], [[['.BWB', '.BW.', 'WBW.', '.BW.', '.BW.', 'WBW.'], [[4, 1]]], ['?BWB', '?BW?', 'WBW?', '?BW?', '??W?', 'WBW?']], [[['.BW.', '.BW.', 'WBW.', '.BW.', '.BW.'], [[0, 1], [3, 1]]], ['??Ww', '?BWw', 'WBWw', '??Ww', '?BWw']], [[['.W..BW', '....BW', 'W...BW', '....BW'], [[1, 4]]], ['?W??BW', '?????W', 'W???BW', '????BW']], [[['..BW', '..BW', 'W.BW', '..BW', '..BW'], [[4, 2], [3, 2]]], ['??BW', '??BW', 'W?BW', '???W', '???W']], [[['.BW...', '.BW...', '.BW...', 'WBW..B', '.BW..B', '.BW..B'], []], ['?BW???', '?BW???', '?BW???', 'WBW??B', '?BW??B', '?BW??B']], [[['BBBB', 'B..B', 'B..B', 'BBBB'], [[0, 2]]], ['BBbB', 'BbbB', 'BbbB', 'BBBB']]], [[[['.BW..', 'WBW..', 'WBWB.', '.BW..', '.BW..'], []], ['?BW??', 'WBW??', 'WBWB?', '?BW??', '?BW??']], [[['...BW', '...BW', '...BW', '...BW', 'W..BW', '.W.BW', '...BW'], [[2, 4], [3, 3]]], ['???BW', '???BW', '???B?', '????W', 'W??BW', '?W?BW', '???BW']], [[['...BW', '..WBW', '...BW', '...BW', '...BW'], []], ['???BW', '??WBW', '???BW', '???BW', '???BW']], [[['...BW', '...BW', '...BW', 'W..BW'], []], ['???BW', '???BW', '???BW', 'W??BW']], [[['..BW.', '..BW.', '..BWB', '..BW.', '..BW.', '..BW.', '..BW.'], [[2, 2], [3, 3]]], ['??BW?', '??BW?', '???WB', '??B??', '??BW?', '??BW?', '??BW?']], [[['.BW..', '.BW.B', '.BWB.', '.BW..', '.BW.B', '.BW..', 'WBW..'], [[4, 1]]], ['?BW??', '?BW?B', '?BWB?', '?BW??', '??W?B', '?BW??', 'WBW??']], [[['..BW', 'W.BW', '..BW', '..BW', '..BW', 'W.BW'], [[0, 2], [5, 3]]], ['???W', 'W?BW', '??BW', '??BW', '??BW', 'W?B?']], [[['..W', '.W.', 'W..'], [[0, 2], [2, 0]]], ['www', 'wWw', 'www']]], [[[['...BW.', '...BW.', '...BW.', '...BW.', '...BW.', '...BW.'], [[2, 4]]], ['bbbBW?', 'bbbBW?', 'bbbB??', 'bbbBW?', 'bbbBW?', 'bbbBW?']], [[['...BW', '...BW', 'W..BW', 'W.WBW', '...BW', '...BW'], []], ['???BW', '???BW', 'W??BW', 'W?WBW', '???BW', '???BW']], [[['....', '....', '....', '....'], []], ['????', '????', '????', '????']], [[['...', '...', '...'], []], ['???', '???', '???']], [[['.B.', 'B.B', '.B.'], [[1, 2], [2, 1]]], ['bBb', 'Bbb', 'bbb']], [[['B..W', 'B..W', 'B..W', 'B..W'], [[2, 3]]], ['B??W', 'B??W', 'B???', 'B??W']], [[['.BW.', '.BW.', '.BW.', '.BW.'], [[0, 2]]], ['bB??', 'bBW?', 'bBW?', 'bBW?']], [[['..B.', '....', '....', '....', 'B...'], [[0, 2]]], ['bbbb', 'bbbb', 'bbbb', 'bbbb', 'Bbbb']]], [[[['.B.', 'B.B', '.B.'], [[1, 2], [2, 1]]], ['bBb', 'Bbb', 'bbb']], [[['B.B.W', '.B.W.', 'B.BW.', 'BBW.W', '..W..'], []], ['BbB?W', 'bB?Ww', 'BbBWw', 'BBWwW', '??Www']], [[['W....', '.....', '.....', '.....', '....B'], [[4, 4]]], ['Wwwww', 'wwwww', 'wwwww', 'wwwww', 'wwwww']], [[['.W.B.', 'W.WB.', '.WB..', 'WB...', 'B....'], [[3, 1], [3, 0]]], ['wW?B?', 'WwWB?', '?WB??', '?????', 'B????']], [[['BBBB', 'B..B', 'B..B', 'BBBB'], [[0, 2]]], ['BBbB', 'BbbB', 'BbbB', 'BBBB']], [[['WWW', 'W.W', 'WWW'], []], ['WWW', 'WwW', 'WWW']], [[['B.W', '...', 'W.B'], [[2, 2], [0, 0]]], ['wwW', 'www', 'Www']], [[['.B...', 'B....', '.....', '....W', '...W.'], [[1, 0]]], ['?B???', '?????', '?????', '????W', '???Ww']]]]
for i, (args, expected) in enumerate(fixtures[N-1]):
check("ownership map 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 |
|---|---|---|---|
| ownership map case 0 | ['?BW?', '??W?', '?BW?', '?BWB', '?BW?', '?BWB'] | ['?BW?', '??W?', '?BW?', '?BWB', '?BW?', '?BWB'] | Passed |
| ownership map case 1 | ['???WBWw', '????BWw', '????BWw', '?W??BWw'] | ['???WBWw', '????BWw', '????BWw', '?W??BWw'] | Passed |
| ownership map case 2 | ['bB?B?', 'bBW??', 'bB???', 'bBWB?'] | ['bB?B?', 'bBW??', 'bB???', 'bBWB?'] | Passed |
| ownership map case 3 | ['WB????', '?BW???', '?BW??B', '?BW???', '?BW???'] | ['WB????', '?BW???', '?BW??B', '?BW???', '?BW???'] | Passed |
| ownership map case 4 | ['?BW?B??', 'WBW????', '?B?????', '?BW????', '?BW????'] | ['?BW?B??', 'WBW????', '?B?????', '?BW????', '?BW????'] | Passed |
| ownership map case 5 | ['????BW', '????BW', '??????', '????BW', '????BW', '????BW'] | ['????BW', '????BW', '??????', '????BW', '????BW', '????BW'] | Passed |
| ownership map case 6 | ['??BW', '??BW', '??BW', '???W', '??BW', '??BW', '??BW'] | ['??BW', '??BW', '??BW', '???W', '??BW', '??BW', '??BW'] | Passed |
| ownership map case 7 | ['bBb', 'Bbb', 'bbb'] | ['bBb', 'Bbb', 'bbb'] | Passed |
SHA-256 / c4b29bb2ce8a0395dd36923d2bcb2ce895c7c89f86b832f7ffde38cf0d3aec97
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.371791+00:00.
Case digest / 336e8533b709de23d0f7f921f7b7d30ef72c2b3ed5e34edd2262841c629029dd