broken_source:
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(x):
    board, komi = x
    n = len(board)
    m = len(board[0])
    b = sum(row.count('B') for row in board)
    w = sum(row.count('W') for row in board)
    seen = set()
    for r in range(n):
        for c in range(m):
            if board[r][c] != '.' or (r, c) in seen:
                continue
            stack = [(r, c)]
            seen.add((r, c))
            size = 0
            border = set()
            while stack:
                i, j = stack.pop()
                size += 1
                for di, dj in ((1, 0), (-1, 0), (0, 1), (0, -1)):
                    a, d = i + di, j + dj
                    if 0 <= a < n and 0 <= d < m:
                        v = board[a][d]
                        if v == '.':
                            if (a, d) not in seen:
                                seen.add((a, d))
                                stack.append((a, d))
                        else:
                            border.add(v)
            if border == {'B'}:
                b += size
            elif border == {'W'}:
                w += size
    diff = b * 10 - w * 10 - komi
    if diff > 0:
        res = 'B+%d.%d' % (diff // 10, diff % 10)
    elif diff < 0:
        res = 'W+%d.%d' % (diff // 10, diff % 10)
    else:
        res = 'Draw'
    return [b, w, res]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[[[['...', '...', '...'], 5], [0, 0, 'W+0.5']], [[['.W.B.', 'W.WB.', '.WB..', 'WB...', 'B....'], 0], [16, 8, 'B+8.0']], [[['BBBB', 'B..B', 'B..B', 'BBBB'], 5], [16, 0, 'B+15.5']], [[['WWW', 'W.W', 'WWW'], 65], [0, 9, 'W+15.5']], [[['B.W', '...', 'W.B'], 75], [2, 2, 'W+7.5']], [[['.B...', 'B....', '.....', '....W', '...W.'], 35], [3, 3, 'W+3.5']], [[['BW.', 'BW.', 'BW.'], 60], [3, 6, 'W+9.0']], [[['B....B', '......', '..WW..', '..WW..', '......', 'B....B'], 5], [4, 4, 'W+0.5']]], [[[['..B..', '..B..', 'BBBBB', 'WWWWW', '..W..'], 60], [15, 10, 'W+1.0']], [[['WB.B', 'B.B.', '.B..', 'B...'], -5], [15, 1, 'B+14.5']], [[['..W', '.W.', 'W..'], 0], [0, 9, 'W+9.0']], [[['B....B', '......', '..WW..', '..WW..', '......', 'B....B'], 5], [4, 4, 'W+0.5']], [[['.BBW.', 'B.BBB', '...W.', '.B.WB'], 65], [9, 3, 'W+0.5']], [[['BB.W.', 'BB.WW', 'W..WW', '.W...', '.B...'], 75], [5, 8, 'W+10.5']], [[['B..', '..W', '...', '.WW'], 35], [1, 3, 'W+5.5']], [[['.B.', '.WW', 'BBB', 'WW.'], 65], [4, 4, 'W+6.5']]], [[[['B.W', '...', 'W.B'], 75], [2, 2, 'W+7.5']], [[['..B', '.WB', 'BW.', '...', '.B.', 'BBB'], 70], [7, 2, 'W+2.0']], [[['WBWWB', 'BB.B.', 'WBWB.', 'WBWBB'], -5], [12, 7, 'B+5.5']], [[['...', '...', '.B.', '.WB', '...', 'B..'], 0], [3, 1, 'B+2.0']], [[['.....', '.W...', 'WW...'], 5], [0, 15, 'W+15.5']], [[['.B.', '.WW', 'BBB', 'WW.'], 65], [4, 4, 'W+6.5']], [[['.B.BB', 'WB...', '.....'], 75], [4, 1, 'W+4.5']], [[['....W', 'BBWWB', 'B..W.', 'W..W.', 'W.W..', '.....'], 35], [4, 8, 'W+7.5']]], [[[['..W', '.W.', 'W..'], 0], [0, 9, 'W+9.0']], [[['B.BW.', 'W.B..', 'W..B.', 'B.B.B'], 60], [8, 3, 'W+1.0']], [[['B..', '.B.', '...', '...', 'B..', 'BB.'], 70], [18, 0, 'B+11.0']], [[['BW.B', '.WWW', 'B.BB', 'WBB.', 'BW.W'], -5], [8, 7, 'B+1.5']], [[['......', '..W...', 'WW.WW.', '......', 'WBW...'], 0], [1, 7, 'W+6.0']], [[['W..W', '.B..', 'B.W.', '.W..', '....'], 5], [2, 4, 'W+2.5']], [[['BWBB.', '.B..B', 'BW..B', 'W.BBW', '...BB'], 65], [13, 4, 'B+2.5']], [[['WWB', 'W.W', 'B.W', 'B..', '..B'], 35], [4, 5, 'W+4.5']]], [[[['BB.W.', 'BB.WW', 'W..WW', '.W...', '.B...'], 75], [5, 8, 'W+10.5']], [[['....W', 'BBWWB', 'B..W.', 'W..W.', 'W.W..', '.....'], 35], [4, 8, 'W+7.5']], [[['W..B.', 'BB.BB', 'B..B.', 'BBB..', 'B.BBB'], 60], [19, 1, 'B+12.0']], [[['.BBBW.', 'WBBBB.', '.WBB..', 'BBB...', 'BBW..B', '..BW.W'], 70], [18, 6, 'B+5.0']], [[['W..BBB', 'BWB.W.', '.WWWWW', 'W.WBWW'], -5], [6, 13, 'W+6.5']], [[['W..B', '...B', 'WWWW'], 0], [2, 5, 'W+3.0']], [[['W...', 'WBWB', 'WWBW', 'BBB.'], 5], [6, 6, 'W+0.5']], [[['WWW.W', '..BWW', 'B.BWB', 'W.B..', '.W.WB', 'WW.W.'], 5], [6, 15, 'W+9.5']]]]
for i, (args, expected) in enumerate(fixtures[N-1]):
    check("area 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)

source:
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(x):
    board, komi = x
    n = len(board)
    m = len(board[0])
    b = sum(row.count('B') for row in board)
    w = sum(row.count('W') for row in board)
    seen = set()
    for r in range(n):
        for c in range(m):
            if board[r][c] != '.' or (r, c) in seen:
                continue
            stack = [(r, c)]
            seen.add((r, c))
            size = 0
            border = set()
            while stack:
                i, j = stack.pop()
                size += 1
                for di, dj in ((1, 0), (-1, 0), (0, 1), (0, -1)):
                    a, d = i + di, j + dj
                    if 0 <= a < n and 0 <= d < m:
                        v = board[a][d]
                        if v == '.':
                            if (a, d) not in seen:
                                seen.add((a, d))
                                stack.append((a, d))
                        else:
                            border.add(v)
            if border == {'B'}:
                b += size
            elif border == {'W'}:
                w += size
    diff = b * 10 - w * 10 - komi
    if diff > 0:
        res = 'B+%d.%d' % (diff // 10, diff % 10)
    elif diff < 0:
        res = 'W+%d.%d' % (abs(diff // 10), abs(diff % 10))
    else:
        res = 'Draw'
    return [b, w, res]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[[[['...', '...', '...'], 5], [0, 0, 'W+0.5']], [[['.W.B.', 'W.WB.', '.WB..', 'WB...', 'B....'], 0], [16, 8, 'B+8.0']], [[['BBBB', 'B..B', 'B..B', 'BBBB'], 5], [16, 0, 'B+15.5']], [[['WWW', 'W.W', 'WWW'], 65], [0, 9, 'W+15.5']], [[['B.W', '...', 'W.B'], 75], [2, 2, 'W+7.5']], [[['.B...', 'B....', '.....', '....W', '...W.'], 35], [3, 3, 'W+3.5']], [[['BW.', 'BW.', 'BW.'], 60], [3, 6, 'W+9.0']], [[['B....B', '......', '..WW..', '..WW..', '......', 'B....B'], 5], [4, 4, 'W+0.5']]], [[[['..B..', '..B..', 'BBBBB', 'WWWWW', '..W..'], 60], [15, 10, 'W+1.0']], [[['WB.B', 'B.B.', '.B..', 'B...'], -5], [15, 1, 'B+14.5']], [[['..W', '.W.', 'W..'], 0], [0, 9, 'W+9.0']], [[['B....B', '......', '..WW..', '..WW..', '......', 'B....B'], 5], [4, 4, 'W+0.5']], [[['.BBW.', 'B.BBB', '...W.', '.B.WB'], 65], [9, 3, 'W+0.5']], [[['BB.W.', 'BB.WW', 'W..WW', '.W...', '.B...'], 75], [5, 8, 'W+10.5']], [[['B..', '..W', '...', '.WW'], 35], [1, 3, 'W+5.5']], [[['.B.', '.WW', 'BBB', 'WW.'], 65], [4, 4, 'W+6.5']]], [[[['B.W', '...', 'W.B'], 75], [2, 2, 'W+7.5']], [[['..B', '.WB', 'BW.', '...', '.B.', 'BBB'], 70], [7, 2, 'W+2.0']], [[['WBWWB', 'BB.B.', 'WBWB.', 'WBWBB'], -5], [12, 7, 'B+5.5']], [[['...', '...', '.B.', '.WB', '...', 'B..'], 0], [3, 1, 'B+2.0']], [[['.....', '.W...', 'WW...'], 5], [0, 15, 'W+15.5']], [[['.B.', '.WW', 'BBB', 'WW.'], 65], [4, 4, 'W+6.5']], [[['.B.BB', 'WB...', '.....'], 75], [4, 1, 'W+4.5']], [[['....W', 'BBWWB', 'B..W.', 'W..W.', 'W.W..', '.....'], 35], [4, 8, 'W+7.5']]], [[[['..W', '.W.', 'W..'], 0], [0, 9, 'W+9.0']], [[['B.BW.', 'W.B..', 'W..B.', 'B.B.B'], 60], [8, 3, 'W+1.0']], [[['B..', '.B.', '...', '...', 'B..', 'BB.'], 70], [18, 0, 'B+11.0']], [[['BW.B', '.WWW', 'B.BB', 'WBB.', 'BW.W'], -5], [8, 7, 'B+1.5']], [[['......', '..W...', 'WW.WW.', '......', 'WBW...'], 0], [1, 7, 'W+6.0']], [[['W..W', '.B..', 'B.W.', '.W..', '....'], 5], [2, 4, 'W+2.5']], [[['BWBB.', '.B..B', 'BW..B', 'W.BBW', '...BB'], 65], [13, 4, 'B+2.5']], [[['WWB', 'W.W', 'B.W', 'B..', '..B'], 35], [4, 5, 'W+4.5']]], [[[['BB.W.', 'BB.WW', 'W..WW', '.W...', '.B...'], 75], [5, 8, 'W+10.5']], [[['....W', 'BBWWB', 'B..W.', 'W..W.', 'W.W..', '.....'], 35], [4, 8, 'W+7.5']], [[['W..B.', 'BB.BB', 'B..B.', 'BBB..', 'B.BBB'], 60], [19, 1, 'B+12.0']], [[['.BBBW.', 'WBBBB.', '.WBB..', 'BBB...', 'BBW..B', '..BW.W'], 70], [18, 6, 'B+5.0']], [[['W..BBB', 'BWB.W.', '.WWWWW', 'W.WBWW'], -5], [6, 13, 'W+6.5']], [[['W..B', '...B', 'WWWW'], 0], [2, 5, 'W+3.0']], [[['W...', 'WBWB', 'WWBW', 'BBB.'], 5], [6, 6, 'W+0.5']], [[['WWW.W', '..BWW', 'B.BWB', 'W.B..', '.W.WB', 'WW.W.'], 5], [6, 15, 'W+9.5']]]]
for i, (args, expected) in enumerate(fixtures[N-1]):
    check("area 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)

prompt:
Results such as W+3.5 are rendered as "W+-4.5".

Input [board, komi_tenths]. Area = own stones + empty regions whose orthogonal border touches only that colour. Return [black_area, white_area, result] where result is "B+x.y" / "W+x.y" after subtracting komi from black, or "Draw".

split: open-access


broken_source:
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(x):
    board, komi = x
    n = len(board)
    m = len(board[0])
    b = sum(row.count('B') for row in board)
    w = sum(row.count('W') for row in board)
    seen = set()
    for r in range(n):
        for c in range(m):
            if board[r][c] != '.' or (r, c) in seen:
                continue
            stack = [(r, c)]
            size = 0
            border = set()
            while stack:
                i, j = stack.pop()
                size += 1
                for di, dj in ((1, 0), (-1, 0), (0, 1), (0, -1)):
                    a, d = i + di, j + dj
                    if 0 <= a < n and 0 <= d < m:
                        v = board[a][d]
                        if v == '.':
                            if (a, d) not in seen:
                                seen.add((a, d))
                                stack.append((a, d))
                        else:
                            border.add(v)
            if border == {'B'}:
                b += size
            elif border == {'W'}:
                w += size
    diff = b * 10 - w * 10 - komi
    if diff > 0:
        res = 'B+%d.%d' % (diff // 10, diff % 10)
    elif diff < 0:
        res = 'W+%d.%d' % ((-diff) // 10, (-diff) % 10)
    else:
        res = 'Draw'
    return [b, w, res]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[[[['.BW.', '.BW.', '.BW.', '.BW.'], 35], [8, 8, 'W+3.5']], [[['.W.B.', 'W.WB.', '.WB..', 'WB...', 'B....'], 0], [16, 8, 'B+8.0']], [[['BBBB', 'B..B', 'B..B', 'BBBB'], 5], [16, 0, 'B+15.5']], [[['WWW', 'W.W', 'WWW'], 65], [0, 9, 'W+15.5']], [[['B.W', '...', 'W.B'], 75], [2, 2, 'W+7.5']], [[['.B...', 'B....', '.....', '....W', '...W.'], 35], [3, 3, 'W+3.5']], [[['BW.', 'BW.', 'BW.'], 60], [3, 6, 'W+9.0']], [[['B..', '.B.', '...', '...', 'B..', 'BB.'], 70], [18, 0, 'B+11.0']]], [[[['.W.B.', 'W.WB.', '.WB..', 'WB...', 'B....'], 0], [16, 8, 'B+8.0']], [[['WB.B', 'B.B.', '.B..', 'B...'], -5], [15, 1, 'B+14.5']], [[['..W', '.W.', 'W..'], 0], [0, 9, 'W+9.0']], [[['B....B', '......', '..WW..', '..WW..', '......', 'B....B'], 5], [4, 4, 'W+0.5']], [[['.BBW.', 'B.BBB', '...W.', '.B.WB'], 65], [9, 3, 'W+0.5']], [[['BB.W.', 'BB.WW', 'W..WW', '.W...', '.B...'], 75], [5, 8, 'W+10.5']], [[['B..', '..W', '...', '.WW'], 35], [1, 3, 'W+5.5']], [[['.BW..', '.BW..', '.BW..', '.BW..', '.BW..', '.BW..'], 70], [12, 18, 'W+13.0']]], [[[['.W.B.', 'W.WB.', '.WB..', 'WB...', 'B....'], 0], [16, 8, 'B+8.0']], [[['.....', '.BBB.', '.B.B.', '.BBB.', '.....'], 70], [25, 0, 'B+18.0']], [[['WBWWB', 'BB.B.', 'WBWB.', 'WBWBB'], -5], [12, 7, 'B+5.5']], [[['...', '...', '.B.', '.WB', '...', 'B..'], 0], [3, 1, 'B+2.0']], [[['.....', '.W...', 'WW...'], 5], [0, 15, 'W+15.5']], [[['.B.', '.WW', 'BBB', 'WW.'], 65], [4, 4, 'W+6.5']], [[['.B.BB', 'WB...', '.....'], 75], [4, 1, 'W+4.5']], [[['.WBB', 'BW..', '..B.'], 35], [4, 2, 'W+1.5']]], [[[['WBWWB', 'BB.B.', 'WBWB.', 'WBWBB'], -5], [12, 7, 'B+5.5']], [[['B.BW.', 'W.B..', 'W..B.', 'B.B.B'], 60], [8, 3, 'W+1.0']], [[['B..', '.B.', '...', '...', 'B..', 'BB.'], 70], [18, 0, 'B+11.0']], [[['BW.B', '.WWW', 'B.BB', 'WBB.', 'BW.W'], -5], [8, 7, 'B+1.5']], [[['......', '..W...', 'WW.WW.', '......', 'WBW...'], 0], [1, 7, 'W+6.0']], [[['W..W', '.B..', 'B.W.', '.W..', '....'], 5], [2, 4, 'W+2.5']], [[['BWBB.', '.B..B', 'BW..B', 'W.BBW', '...BB'], 65], [13, 4, 'B+2.5']], [[['...W..', '..WBW.', 'W...WW', '.WW..W'], 75], [1, 13, 'W+19.5']]], [[[['...W..', '..WBW.', 'W...WW', '.WW..W'], 75], [1, 13, 'W+19.5']], [[['....W', 'BBWWB', 'B..W.', 'W..W.', 'W.W..', '.....'], 35], [4, 8, 'W+7.5']], [[['W..B.', 'BB.BB', 'B..B.', 'BBB..', 'B.BBB'], 60], [19, 1, 'B+12.0']], [[['.BBBW.', 'WBBBB.', '.WBB..', 'BBB...', 'BBW..B', '..BW.W'], 70], [18, 6, 'B+5.0']], [[['W..BBB', 'BWB.W.', '.WWWWW', 'W.WBWW'], -5], [6, 13, 'W+6.5']], [[['W..B', '...B', 'WWWW'], 0], [2, 5, 'W+3.0']], [[['W...', 'WBWB', 'WWBW', 'BBB.'], 5], [6, 6, 'W+0.5']], [[['.BW..', '.BW..', '.BW..', '.BW..', '.BW..', '.BW..'], 70], [12, 18, 'W+13.0']]]]
for i, (args, expected) in enumerate(fixtures[N-1]):
    check("area 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)

meaning: Fixture-count band, not measured model difficulty

deps: stdlib

source:
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(x):
    board, komi = x
    n = len(board)
    m = len(board[0])
    b = sum(row.count('B') for row in board)
    w = sum(row.count('W') for row in board)
    seen = set()
    for r in range(n):
        for c in range(m):
            if board[r][c] != '.' or (r, c) in seen:
                continue
            stack = [(r, c)]
            size = 0
            border = set()
            while stack:
                i, j = stack.pop()
                seen.add((i, j))
                size += 1
                for di, dj in ((1, 0), (-1, 0), (0, 1), (0, -1)):
                    a, d = i + di, j + dj
                    if 0 <= a < n and 0 <= d < m:
                        v = board[a][d]
                        if v == '.':
                            if (a, d) not in seen:
                                stack.append((a, d))
                        else:
                            border.add(v)
            if border == {'B'}:
                b += size
            elif border == {'W'}:
                w += size
    diff = b * 10 - w * 10 - komi
    if diff > 0:
        res = 'B+%d.%d' % (diff // 10, diff % 10)
    elif diff < 0:
        res = 'W+%d.%d' % ((-diff) // 10, (-diff) % 10)
    else:
        res = 'Draw'
    return [b, w, res]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[[[['.BW.', '.BW.', '.BW.', '.BW.'], 35], [8, 8, 'W+3.5']], [[['.W.B.', 'W.WB.', '.WB..', 'WB...', 'B....'], 0], [16, 8, 'B+8.0']], [[['BBBB', 'B..B', 'B..B', 'BBBB'], 5], [16, 0, 'B+15.5']], [[['WWW', 'W.W', 'WWW'], 65], [0, 9, 'W+15.5']], [[['B.W', '...', 'W.B'], 75], [2, 2, 'W+7.5']], [[['.B...', 'B....', '.....', '....W', '...W.'], 35], [3, 3, 'W+3.5']], [[['BW.', 'BW.', 'BW.'], 60], [3, 6, 'W+9.0']], [[['B..', '.B.', '...', '...', 'B..', 'BB.'], 70], [18, 0, 'B+11.0']]], [[[['.W.B.', 'W.WB.', '.WB..', 'WB...', 'B....'], 0], [16, 8, 'B+8.0']], [[['WB.B', 'B.B.', '.B..', 'B...'], -5], [15, 1, 'B+14.5']], [[['..W', '.W.', 'W..'], 0], [0, 9, 'W+9.0']], [[['B....B', '......', '..WW..', '..WW..', '......', 'B....B'], 5], [4, 4, 'W+0.5']], [[['.BBW.', 'B.BBB', '...W.', '.B.WB'], 65], [9, 3, 'W+0.5']], [[['BB.W.', 'BB.WW', 'W..WW', '.W...', '.B...'], 75], [5, 8, 'W+10.5']], [[['B..', '..W', '...', '.WW'], 35], [1, 3, 'W+5.5']], [[['.BW..', '.BW..', '.BW..', '.BW..', '.BW..', '.BW..'], 70], [12, 18, 'W+13.0']]], [[[['.W.B.', 'W.WB.', '.WB..', 'WB...', 'B....'], 0], [16, 8, 'B+8.0']], [[['.....', '.BBB.', '.B.B.', '.BBB.', '.....'], 70], [25, 0, 'B+18.0']], [[['WBWWB', 'BB.B.', 'WBWB.', 'WBWBB'], -5], [12, 7, 'B+5.5']], [[['...', '...', '.B.', '.WB', '...', 'B..'], 0], [3, 1, 'B+2.0']], [[['.....', '.W...', 'WW...'], 5], [0, 15, 'W+15.5']], [[['.B.', '.WW', 'BBB', 'WW.'], 65], [4, 4, 'W+6.5']], [[['.B.BB', 'WB...', '.....'], 75], [4, 1, 'W+4.5']], [[['.WBB', 'BW..', '..B.'], 35], [4, 2, 'W+1.5']]], [[[['WBWWB', 'BB.B.', 'WBWB.', 'WBWBB'], -5], [12, 7, 'B+5.5']], [[['B.BW.', 'W.B..', 'W..B.', 'B.B.B'], 60], [8, 3, 'W+1.0']], [[['B..', '.B.', '...', '...', 'B..', 'BB.'], 70], [18, 0, 'B+11.0']], [[['BW.B', '.WWW', 'B.BB', 'WBB.', 'BW.W'], -5], [8, 7, 'B+1.5']], [[['......', '..W...', 'WW.WW.', '......', 'WBW...'], 0], [1, 7, 'W+6.0']], [[['W..W', '.B..', 'B.W.', '.W..', '....'], 5], [2, 4, 'W+2.5']], [[['BWBB.', '.B..B', 'BW..B', 'W.BBW', '...BB'], 65], [13, 4, 'B+2.5']], [[['...W..', '..WBW.', 'W...WW', '.WW..W'], 75], [1, 13, 'W+19.5']]], [[[['...W..', '..WBW.', 'W...WW', '.WW..W'], 75], [1, 13, 'W+19.5']], [[['....W', 'BBWWB', 'B..W.', 'W..W.', 'W.W..', '.....'], 35], [4, 8, 'W+7.5']], [[['W..B.', 'BB.BB', 'B..B.', 'BBB..', 'B.BBB'], 60], [19, 1, 'B+12.0']], [[['.BBBW.', 'WBBBB.', '.WBB..', 'BBB...', 'BBW..B', '..BW.W'], 70], [18, 6, 'B+5.0']], [[['W..BBB', 'BWB.W.', '.WWWWW', 'W.WBWW'], -5], [6, 13, 'W+6.5']], [[['W..B', '...B', 'WWWW'], 0], [2, 5, 'W+3.0']], [[['W...', 'WBWB', 'WWBW', 'BBB.'], 5], [6, 6, 'W+0.5']], [[['.BW..', '.BW..', '.BW..', '.BW..', '.BW..', '.BW..'], 70], [12, 18, 'W+13.0']]]]
for i, (args, expected) in enumerate(fixtures[N-1]):
    check("area 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)

prompt:
Some enclosed regions are one point larger than they are on the board.

Input [board, komi_tenths]. Area = own stones + empty regions whose orthogonal border touches only that colour. Return [black_area, white_area, result] where result is "B+x.y" / "W+x.y" after subtracting komi from black, or "Draw".

split: open-access


broken_source:
"""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)

source:
"""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)

prompt:
Marking a white group dead raises white prisoner count instead of black.

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".

split: open-access


broken_source:
"""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
    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']], [[['...BW..', '...BWB.', '...BW..', '...BW..', '...BW..'], [[0, 3], [0, 3], [4, 2]], 0, 1, 5], [0, 0, 0, 2, 'W+2.5']]], [[[['..BW.', '..BW.', '..BW.', '..BWB', '..BW.', '..BW.'], [[3, 2], [3, 2]], 1, 1, 0], [0, 0, 1, 2, 'W+1.0']], [[['....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', '.W...BW', '.....BW'], [[3, 5], [1, 5], [3, 6], [3, 5]], 0, 3, 5], [0, 0, 1, 5, '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.', '.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']], [[['.B.', 'B.B', '.B.'], [[0, 1], [2, 1], [0, 1]], 0, 1, 5], [7, 0, 0, 3, 'B+3.5']]], [[[['..BW', '..BW', '..BW', '..BW', '..BW', '..BW', '..BW'], [[0, 2], [6, 2], [5, 3]], 1, 1, 0], [0, 0, 2, 3, 'W+1.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']], [[['WWW', 'W.W', 'WWW'], [[0, 1], [2, 2]], 1, 3, 65], [0, 3, 3, 3, 'W+9.5']]], [[[['..BW', '.WBW', '..BW', '..BW', '..BW', '..BW'], [[1, 3], [3, 3], [1, 3]], 4, 1, 55], [0, 0, 6, 1, 'W+0.5']], [[['...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', 'BW.B', 'BB.B', 'B...', '..B.', '.BBB'], [[2, 0], [2, 0]], 1, 2, 0], [1, 0, 1, 3, 'W+1.0']]]]
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)

source:
"""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] = 'W' if g[r][c] == 'B' else 'B'
    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']], [[['...BW..', '...BWB.', '...BW..', '...BW..', '...BW..'], [[0, 3], [0, 3], [4, 2]], 0, 1, 5], [0, 0, 0, 2, 'W+2.5']]], [[[['..BW.', '..BW.', '..BW.', '..BWB', '..BW.', '..BW.'], [[3, 2], [3, 2]], 1, 1, 0], [0, 0, 1, 2, 'W+1.0']], [[['....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', '.W...BW', '.....BW'], [[3, 5], [1, 5], [3, 6], [3, 5]], 0, 3, 5], [0, 0, 1, 5, '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.', '.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']], [[['.B.', 'B.B', '.B.'], [[0, 1], [2, 1], [0, 1]], 0, 1, 5], [7, 0, 0, 3, 'B+3.5']]], [[[['..BW', '..BW', '..BW', '..BW', '..BW', '..BW', '..BW'], [[0, 2], [6, 2], [5, 3]], 1, 1, 0], [0, 0, 2, 3, 'W+1.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']], [[['WWW', 'W.W', 'WWW'], [[0, 1], [2, 2]], 1, 3, 65], [0, 3, 3, 3, 'W+9.5']]], [[[['..BW', '.WBW', '..BW', '..BW', '..BW', '..BW'], [[1, 3], [3, 3], [1, 3]], 4, 1, 55], [0, 0, 6, 1, 'W+0.5']], [[['...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', 'BW.B', 'BB.B', 'B...', '..B.', '.BBB'], [[2, 0], [2, 0]], 1, 2, 0], [1, 0, 1, 3, 'W+1.0']]]]
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)

prompt:
Territory around a dead invader is scored as dame and the dead point itself is never territory.

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".

split: open-access


broken_source:
"""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 board[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 = [[[[['.WBW..', '..BW.B', '..BW..', '..BW..', '..BWB.', 'WWBW..'], [[4, 4], [0, 1], [4, 4]], 4, 4, 60], [0, 0, 5, 5, 'W+6.0']], [[['..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']], [[['BBB', 'BWB', 'BBB'], [[1, 1], [1, 1]], 1, 0, 65], [1, 0, 2, 0, 'W+3.5']]], [[[['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.', '.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.', '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']], [[['W..BWW', 'BBW..W', '..WB..', '....WB', 'WWWWW.', 'WWB...'], [[0, 5], [4, 5]], 2, 2, 55], [0, 1, 3, 2, 'W+5.5']]], [[[['..BW', '..BW', '.WBW', '.WBW', '..BW'], [[0, 3], [4, 2], [3, 0]], 0, 0, 60], [0, 0, 1, 1, 'W+6.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']], [[['..B..', '..B..', 'BBBBB', 'WWWWW', '..W..'], [[4, 2]], 4, 3, 55], [8, 5, 5, 3, 'W+0.5']], [[['..W.W', 'B.BB.', 'BBB..'], [[0, 4], [2, 0]], 1, 1, 65], [1, 0, 2, 2, 'W+5.5']]], [[[['W..BWB', '...BW.', '...BW.', '...BWB'], [[0, 5]], 4, 0, 5], [0, 0, 4, 1, 'B+2.5']], [[['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']], [[['BBBB', 'B..B', 'B..B', 'BBBB'], [[2, 0], [1, 3], [2, 0]], 0, 4, 5], [6, 0, 0, 6, 'W+0.5']], [[['WWW', 'W.W', 'WWW'], [[0, 1], [2, 2]], 1, 3, 65], [0, 3, 3, 3, 'W+9.5']]], [[[['...BWB.', '...BW..', '...BW..', '...BW..', '...BW..'], [[1, 4], [2, 4], [4, 3]], 2, 1, 5], [0, 0, 4, 2, 'B+1.5']], [[['...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']], [[['..W', '.W.', 'W..'], [[0, 2], [2, 0]], 3, 2, 60], [0, 8, 5, 2, 'W+11.0']], [[['BBB', 'BWB', 'BBB'], [[1, 1]], 0, 0, 0], [1, 0, 1, 0, 'B+2.0']]]]
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)

source:
"""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 board[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 = [[[[['.WBW..', '..BW.B', '..BW..', '..BW..', '..BWB.', 'WWBW..'], [[4, 4], [0, 1], [4, 4]], 4, 4, 60], [0, 0, 5, 5, 'W+6.0']], [[['..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']], [[['BBB', 'BWB', 'BBB'], [[1, 1], [1, 1]], 1, 0, 65], [1, 0, 2, 0, 'W+3.5']]], [[[['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.', '.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.', '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']], [[['W..BWW', 'BBW..W', '..WB..', '....WB', 'WWWWW.', 'WWB...'], [[0, 5], [4, 5]], 2, 2, 55], [0, 1, 3, 2, 'W+5.5']]], [[[['..BW', '..BW', '.WBW', '.WBW', '..BW'], [[0, 3], [4, 2], [3, 0]], 0, 0, 60], [0, 0, 1, 1, 'W+6.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']], [[['..B..', '..B..', 'BBBBB', 'WWWWW', '..W..'], [[4, 2]], 4, 3, 55], [8, 5, 5, 3, 'W+0.5']], [[['..W.W', 'B.BB.', 'BBB..'], [[0, 4], [2, 0]], 1, 1, 65], [1, 0, 2, 2, 'W+5.5']]], [[[['W..BWB', '...BW.', '...BW.', '...BWB'], [[0, 5]], 4, 0, 5], [0, 0, 4, 1, 'B+2.5']], [[['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']], [[['BBBB', 'B..B', 'B..B', 'BBBB'], [[2, 0], [1, 3], [2, 0]], 0, 4, 5], [6, 0, 0, 6, 'W+0.5']], [[['WWW', 'W.W', 'WWW'], [[0, 1], [2, 2]], 1, 3, 65], [0, 3, 3, 3, 'W+9.5']]], [[[['...BWB.', '...BW..', '...BW..', '...BW..', '...BW..'], [[1, 4], [2, 4], [4, 3]], 2, 1, 5], [0, 0, 4, 2, 'B+1.5']], [[['...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']], [[['..W', '.W.', 'W..'], [[0, 2], [2, 0]], 3, 2, 60], [0, 8, 5, 2, 'W+11.0']], [[['BBB', 'BWB', 'BBB'], [[1, 1]], 0, 0, 0], [1, 0, 1, 0, 'B+2.0']]]]
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)

prompt:
Regions that should absorb removed dead stones stay neutral.

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".

split: open-access


broken_source:
"""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 = [[[[['.WBW..', '..BW.B', '..BW..', '..BW..', '..BWB.', 'WWBW..'], [[4, 4], [0, 1], [4, 4]], 4, 4, 60], [0, 0, 5, 5, 'W+6.0']], [[['..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']], [[['..BW..', '..BW.B', '..BW..', '..BW.B', 'W.BW..', '..BW..', '..BW..'], [[2, 2], [2, 2]], 2, 1, 0], [0, 0, 2, 2, 'Jigo']], [[['W....', 'BB.BB', 'W..B.', 'B.B..', 'BWB.W'], [], 4, 4, 0], [0, 0, 4, 4, 'Jigo']]], [[[['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.', '.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']], [[['B.W', 'B.W', 'B.W'], [], 0, 0, 0], [0, 0, 0, 0, 'Jigo']], [[['B.W', 'B.W', 'B.W'], [], 0, 0, 0], [0, 0, 0, 0, 'Jigo']]], [[[['..BW', '..BW', '.WBW', '.WBW', '..BW'], [[0, 3], [4, 2], [3, 0]], 0, 0, 60], [0, 0, 1, 1, 'W+6.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....', 'BB.BB', 'W..B.', 'B.B..', 'BWB.W'], [], 4, 4, 0], [0, 0, 4, 4, 'Jigo']]], [[[['W..BWB', '...BW.', '...BW.', '...BWB'], [[0, 5]], 4, 0, 5], [0, 0, 4, 1, 'B+2.5']], [[['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']], [[['...BW', '...BW', 'W..BW', '...BW', '.W.BW', '...BW', 'W..BW'], [], 1, 1, 0], [0, 0, 1, 1, 'Jigo']], [[['...BW', '...BW', 'W..BW', '...BW', '.W.BW', '...BW', 'W..BW'], [], 1, 1, 0], [0, 0, 1, 1, 'Jigo']]], [[[['..BW..', '..BW.B', '..BW..', '..BW.B', 'W.BW..', '..BW..', '..BW..'], [[2, 2], [2, 2]], 2, 1, 0], [0, 0, 2, 2, 'Jigo']], [[['...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']], [[['W....', 'BB.BB', 'W..B.', 'B.B..', 'BWB.W'], [], 4, 4, 0], [0, 0, 4, 4, 'Jigo']]]]
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)

source:
"""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 = 'Draw'
    return [tb, tw, pb, pw, res]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[[[['.WBW..', '..BW.B', '..BW..', '..BW..', '..BWB.', 'WWBW..'], [[4, 4], [0, 1], [4, 4]], 4, 4, 60], [0, 0, 5, 5, 'W+6.0']], [[['..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']], [[['..BW..', '..BW.B', '..BW..', '..BW.B', 'W.BW..', '..BW..', '..BW..'], [[2, 2], [2, 2]], 2, 1, 0], [0, 0, 2, 2, 'Jigo']], [[['W....', 'BB.BB', 'W..B.', 'B.B..', 'BWB.W'], [], 4, 4, 0], [0, 0, 4, 4, 'Jigo']]], [[[['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.', '.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']], [[['B.W', 'B.W', 'B.W'], [], 0, 0, 0], [0, 0, 0, 0, 'Jigo']], [[['B.W', 'B.W', 'B.W'], [], 0, 0, 0], [0, 0, 0, 0, 'Jigo']]], [[[['..BW', '..BW', '.WBW', '.WBW', '..BW'], [[0, 3], [4, 2], [3, 0]], 0, 0, 60], [0, 0, 1, 1, 'W+6.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....', 'BB.BB', 'W..B.', 'B.B..', 'BWB.W'], [], 4, 4, 0], [0, 0, 4, 4, 'Jigo']]], [[[['W..BWB', '...BW.', '...BW.', '...BWB'], [[0, 5]], 4, 0, 5], [0, 0, 4, 1, 'B+2.5']], [[['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']], [[['...BW', '...BW', 'W..BW', '...BW', '.W.BW', '...BW', 'W..BW'], [], 1, 1, 0], [0, 0, 1, 1, 'Jigo']], [[['...BW', '...BW', 'W..BW', '...BW', '.W.BW', '...BW', 'W..BW'], [], 1, 1, 0], [0, 0, 1, 1, 'Jigo']]], [[[['..BW..', '..BW.B', '..BW..', '..BW.B', 'W.BW..', '..BW..', '..BW..'], [[2, 2], [2, 2]], 2, 1, 0], [0, 0, 2, 2, 'Jigo']], [[['...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']], [[['W....', 'BB.BB', 'W..B.', 'B.B..', 'BWB.W'], [], 4, 4, 0], [0, 0, 4, 4, 'Jigo']]]]
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)

prompt:
A zero-margin game with integer komi prints B+0.0.

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".

split: open-access


broken_source:
"""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
    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']], [[['..BW..', '..BW.B', '..BW..', '..BW..', '..BW..', '..BW..'], [[3, 3], [2, 3]], 1, 2, 5], [12, 0, 3, 2, 'B+12.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']]], [[[['WBW.', '.BWB', '.BW.', '.BW.', '.BW.'], [], 4, 2, 55], [0, 0, 4, 2, 'W+3.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', '.WBW', '.WBW', '..BW'], [[0, 3], [4, 2], [3, 0]], 0, 0, 60], [0, 0, 1, 1, 'W+6.0']]], [[[['..BW..', '..BW.B', '..BW..', '..BW..', '..BW..', '..BW..'], [[3, 3], [2, 3]], 1, 2, 5], [12, 0, 3, 2, 'B+12.5']], [[['.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']]], [[[['.....BW', '....WBW', '.W...BW', '..W..BW', '...W.BW'], [[4, 5]], 0, 0, 65], [0, 0, 0, 1, 'W+7.5']], [[['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']], [[['...BWB.', '...BW..', '...BW..', '...BW..', '...BW..'], [[1, 4], [2, 4], [4, 3]], 2, 1, 5], [0, 0, 4, 2, 'B+1.5']]], [[[['....BW.', '....BW.', '.W..BW.', '...WBW.', '...WBWB', '....BW.'], [[5, 1]], 4, 3, 55], [0, 0, 4, 3, 'W+4.5']], [[['...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.B', '.B.'], [[0, 1], [2, 1], [0, 1]], 0, 1, 5], [7, 0, 0, 3, 'B+3.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)

source:
"""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 + komi // 10) * 10
    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']], [[['..BW..', '..BW.B', '..BW..', '..BW..', '..BW..', '..BW..'], [[3, 3], [2, 3]], 1, 2, 5], [12, 0, 3, 2, 'B+12.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']]], [[[['WBW.', '.BWB', '.BW.', '.BW.', '.BW.'], [], 4, 2, 55], [0, 0, 4, 2, 'W+3.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', '.WBW', '.WBW', '..BW'], [[0, 3], [4, 2], [3, 0]], 0, 0, 60], [0, 0, 1, 1, 'W+6.0']]], [[[['..BW..', '..BW.B', '..BW..', '..BW..', '..BW..', '..BW..'], [[3, 3], [2, 3]], 1, 2, 5], [12, 0, 3, 2, 'B+12.5']], [[['.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']]], [[[['.....BW', '....WBW', '.W...BW', '..W..BW', '...W.BW'], [[4, 5]], 0, 0, 65], [0, 0, 0, 1, 'W+7.5']], [[['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']], [[['...BWB.', '...BW..', '...BW..', '...BW..', '...BW..'], [[1, 4], [2, 4], [4, 3]], 2, 1, 5], [0, 0, 4, 2, 'B+1.5']]], [[[['....BW.', '....BW.', '.W..BW.', '...WBW.', '...WBWB', '....BW.'], [[5, 1]], 4, 3, 55], [0, 0, 4, 3, 'W+4.5']], [[['...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.B', '.B.'], [[0, 1], [2, 1], [0, 1]], 0, 1, 5], [7, 0, 0, 3, 'B+3.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)

prompt:
White totals ignore compensation, so black wins close games it lost.

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".

split: open-access


broken_source:
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(x):
    board, color, r, c = x
    g = [list(row) for row in board]
    n = len(g)
    m = len(g[0])
    if g[r][c] != '.':
        return ['illegal', 'occupied']
    opp = 'W' if color == 'B' else 'B'
    g[r][c] = color
    def group(i, j):
        col = g[i][j]
        stones = {(i, j)}
        libs = set()
        stack = [(i, j)]
        while stack:
            a, b = stack.pop()
            for p, q in ((a, b + 1), (a + 1, b), (a, b - 1), (a - 1, b)):
                if 0 <= p < n and 0 <= q < m:
                    if g[p][q] == '.':
                        libs.add((p, q))
                    elif g[p][q] == col and (p, q) not in stones:
                        stones.add((p, q))
                        stack.append((p, q))
        return stones, libs
    own, own_libs = group(r, c)
    if not own_libs:
        return ['illegal', 'suicide']
    captured = 0
    for p, q in ((r + 1, c), (r - 1, c), (r, c + 1), (r, c - 1)):
        if 0 <= p < n and 0 <= q < m and g[p][q] == opp:
            stones, libs = group(p, q)
            if not libs:
                for s, t in stones:
                    g[s][t] = '.'
                captured += len(stones)
    stones, libs = group(r, c)
    if not libs:
        return ['illegal', 'suicide']
    return [[''.join(row) for row in g], captured]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[[[['...', '...', '...'], 'W', 2, 0], [['...', '...', 'W..'], 0]], [[['.B.', 'B.B', '.B.'], 'W', 2, 2], ['illegal', 'suicide']], [[['.B.', 'B.B', '.B.'], 'W', 2, 0], ['illegal', 'suicide']], [[['.B.', 'B.B', '.B.'], 'B', 0, 0], [['BB.', 'B.B', '.B.'], 0]], [[['.B.', 'B.B', '.B.'], 'B', 0, 2], [['.BB', 'B.B', '.B.'], 0]], [[['.B.', 'B.B', '.B.'], 'B', 0, 1], ['illegal', 'occupied']], [[['WWBW', 'WBBW', 'WBB.'], 'W', 2, 3], [['WW.W', 'W..W', 'W..W'], 5]], [[['...', '.BW', '..B', '.BW', 'BB.'], 'W', 4, 2], ['illegal', 'suicide']]], [[[['B..W', 'B..W', 'B..W', 'B..W'], 'B', 1, 1], [['B..W', 'BB.W', 'B..W', 'B..W'], 0]], [[['B..W', 'B..W', 'B..W', 'B..W'], 'W', 0, 2], [['B.WW', 'B..W', 'B..W', 'B..W'], 0]], [[['B..W', 'B..W', 'B..W', 'B..W'], 'B', 0, 1], [['BB.W', 'B..W', 'B..W', 'B..W'], 0]], [[['B..W', 'B..W', 'B..W', 'B..W'], 'B', 2, 0], ['illegal', 'occupied']], [[['.BW.', '.BW.', '.BW.', '.BW.'], 'W', 2, 3], [['.BW.', '.BW.', '.BWW', '.BW.'], 0]], [[['.BW.', '.BW.', '.BW.', '.BW.'], 'W', 0, 0], [['WBW.', '.BW.', '.BW.', '.BW.'], 0]], [[['W.WW.', '...BW', '...W.'], 'B', 2, 4], ['illegal', 'suicide']], [[['WBW', 'BBB', 'BB.'], 'W', 2, 2], [['W.W', '...', '..W'], 6]]], [[[['.BW.', '.BW.', '.BW.', '.BW.'], 'B', 2, 0], [['.BW.', '.BW.', 'BBW.', '.BW.'], 0]], [[['.BW.', '.BW.', '.BW.', '.BW.'], 'B', 0, 2], ['illegal', 'occupied']], [[['..B..', '..B..', 'BBBBB', 'WWWWW', '..W..'], 'B', 0, 0], [['B.B..', '..B..', 'BBBBB', 'WWWWW', '..W..'], 0]], [[['..B..', '..B..', 'BBBBB', 'WWWWW', '..W..'], 'B', 1, 1], [['..B..', '.BB..', 'BBBBB', 'WWWWW', '..W..'], 0]], [[['..B..', '..B..', 'BBBBB', 'WWWWW', '..W..'], 'B', 4, 0], [['..B..', '..B..', 'BBBBB', 'WWWWW', 'B.W..'], 0]], [[['..B..', '..B..', 'BBBBB', 'WWWWW', '..W..'], 'B', 0, 1], [['.BB..', '..B..', 'BBBBB', 'WWWWW', '..W..'], 0]], [[['.B.', 'BWB', '...'], 'W', 0, 0], ['illegal', 'suicide']], [[['B.B', 'WBW', '.W.'], 'B', 2, 2], [['B.B', 'WB.', '.WB'], 1]]], [[[['B.B.W', '.B.W.', 'B.BW.', 'BBW.W', '..W..'], 'W', 2, 1], ['illegal', 'suicide']], [[['B.B.W', '.B.W.', 'B.BW.', 'BBW.W', '..W..'], 'W', 0, 1], ['illegal', 'suicide']], [[['B.B.W', '.B.W.', 'B.BW.', 'BBW.W', '..W..'], 'B', 4, 3], [['B.B.W', '.B.W.', 'B.BW.', 'BBW.W', '..WB.'], 0]], [[['B.B.W', '.B.W.', 'B.BW.', 'BBW.W', '..W..'], 'B', 2, 4], [['B.B.W', '.B.W.', 'B.BWB', 'BBW.W', '..W..'], 0]], [[['B.B.W', '.B.W.', 'B.BW.', 'BBW.W', '..W..'], 'B', 3, 2], ['illegal', 'occupied']], [[['W....', '.....', '.....', '.....', '....B'], 'W', 4, 1], [['W....', '.....', '.....', '.....', '.W..B'], 0]], [[['.W.', 'WBW', 'BWB'], 'B', 0, 2], [['.WB', 'WB.', 'BWB'], 1]], [[['BWB', 'W.W', 'BWB'], 'W', 1, 1], ['illegal', 'suicide']]], [[[['W....', '.....', '.....', '.....', '....B'], 'W', 3, 0], [['W....', '.....', '.....', 'W....', '....B'], 0]], [[['W....', '.....', '.....', '.....', '....B'], 'W', 4, 0], [['W....', '.....', '.....', '.....', 'W...B'], 0]], [[['W....', '.....', '.....', '.....', '....B'], 'B', 4, 4], ['illegal', 'occupied']], [[['.W.B.', 'W.WB.', '.WB..', 'WB...', 'B....'], 'W', 0, 2], [['.WWB.', 'W.WB.', '.WB..', 'WB...', 'B....'], 0]], [[['.W.B.', 'W.WB.', '.WB..', 'WB...', 'B....'], 'W', 0, 0], [['WW.B.', 'W.WB.', '.WB..', 'WB...', 'B....'], 0]], [[['.W.B.', 'W.WB.', '.WB..', 'WB...', 'B....'], 'B', 2, 4], [['.W.B.', 'W.WB.', '.WB.B', 'WB...', 'B....'], 0]], [[['WWW', 'W.W', 'WWW'], 'W', 1, 1], ['illegal', 'suicide']], [[['BWB', 'W.W', 'BWB'], 'B', 1, 1], [['B.B', '.B.', 'B.B'], 4]]]]
for i, (args, expected) in enumerate(fixtures[N-1]):
    check("move result 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)

source:
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(x):
    board, color, r, c = x
    g = [list(row) for row in board]
    n = len(g)
    m = len(g[0])
    if g[r][c] != '.':
        return ['illegal', 'occupied']
    opp = 'W' if color == 'B' else 'B'
    g[r][c] = color
    def group(i, j):
        col = g[i][j]
        stones = {(i, j)}
        libs = set()
        stack = [(i, j)]
        while stack:
            a, b = stack.pop()
            for p, q in ((a, b + 1), (a + 1, b), (a, b - 1), (a - 1, b)):
                if 0 <= p < n and 0 <= q < m:
                    if g[p][q] == '.':
                        libs.add((p, q))
                    elif g[p][q] == col and (p, q) not in stones:
                        stones.add((p, q))
                        stack.append((p, q))
        return stones, libs
    captured = 0
    for p, q in ((r + 1, c), (r - 1, c), (r, c + 1), (r, c - 1)):
        if 0 <= p < n and 0 <= q < m and g[p][q] == opp:
            stones, libs = group(p, q)
            if not libs:
                for s, t in stones:
                    g[s][t] = '.'
                captured += len(stones)
    return [[''.join(row) for row in g], captured]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[[[['...', '...', '...'], 'W', 2, 0], [['...', '...', 'W..'], 0]], [[['.B.', 'B.B', '.B.'], 'W', 2, 2], ['illegal', 'suicide']], [[['.B.', 'B.B', '.B.'], 'W', 2, 0], ['illegal', 'suicide']], [[['.B.', 'B.B', '.B.'], 'B', 0, 0], [['BB.', 'B.B', '.B.'], 0]], [[['.B.', 'B.B', '.B.'], 'B', 0, 2], [['.BB', 'B.B', '.B.'], 0]], [[['.B.', 'B.B', '.B.'], 'B', 0, 1], ['illegal', 'occupied']], [[['WWBW', 'WBBW', 'WBB.'], 'W', 2, 3], [['WW.W', 'W..W', 'W..W'], 5]], [[['...', '.BW', '..B', '.BW', 'BB.'], 'W', 4, 2], ['illegal', 'suicide']]], [[[['B..W', 'B..W', 'B..W', 'B..W'], 'B', 1, 1], [['B..W', 'BB.W', 'B..W', 'B..W'], 0]], [[['B..W', 'B..W', 'B..W', 'B..W'], 'W', 0, 2], [['B.WW', 'B..W', 'B..W', 'B..W'], 0]], [[['B..W', 'B..W', 'B..W', 'B..W'], 'B', 0, 1], [['BB.W', 'B..W', 'B..W', 'B..W'], 0]], [[['B..W', 'B..W', 'B..W', 'B..W'], 'B', 2, 0], ['illegal', 'occupied']], [[['.BW.', '.BW.', '.BW.', '.BW.'], 'W', 2, 3], [['.BW.', '.BW.', '.BWW', '.BW.'], 0]], [[['.BW.', '.BW.', '.BW.', '.BW.'], 'W', 0, 0], [['WBW.', '.BW.', '.BW.', '.BW.'], 0]], [[['W.WW.', '...BW', '...W.'], 'B', 2, 4], ['illegal', 'suicide']], [[['WBW', 'BBB', 'BB.'], 'W', 2, 2], [['W.W', '...', '..W'], 6]]], [[[['.BW.', '.BW.', '.BW.', '.BW.'], 'B', 2, 0], [['.BW.', '.BW.', 'BBW.', '.BW.'], 0]], [[['.BW.', '.BW.', '.BW.', '.BW.'], 'B', 0, 2], ['illegal', 'occupied']], [[['..B..', '..B..', 'BBBBB', 'WWWWW', '..W..'], 'B', 0, 0], [['B.B..', '..B..', 'BBBBB', 'WWWWW', '..W..'], 0]], [[['..B..', '..B..', 'BBBBB', 'WWWWW', '..W..'], 'B', 1, 1], [['..B..', '.BB..', 'BBBBB', 'WWWWW', '..W..'], 0]], [[['..B..', '..B..', 'BBBBB', 'WWWWW', '..W..'], 'B', 4, 0], [['..B..', '..B..', 'BBBBB', 'WWWWW', 'B.W..'], 0]], [[['..B..', '..B..', 'BBBBB', 'WWWWW', '..W..'], 'B', 0, 1], [['.BB..', '..B..', 'BBBBB', 'WWWWW', '..W..'], 0]], [[['.B.', 'BWB', '...'], 'W', 0, 0], ['illegal', 'suicide']], [[['B.B', 'WBW', '.W.'], 'B', 2, 2], [['B.B', 'WB.', '.WB'], 1]]], [[[['B.B.W', '.B.W.', 'B.BW.', 'BBW.W', '..W..'], 'W', 2, 1], ['illegal', 'suicide']], [[['B.B.W', '.B.W.', 'B.BW.', 'BBW.W', '..W..'], 'W', 0, 1], ['illegal', 'suicide']], [[['B.B.W', '.B.W.', 'B.BW.', 'BBW.W', '..W..'], 'B', 4, 3], [['B.B.W', '.B.W.', 'B.BW.', 'BBW.W', '..WB.'], 0]], [[['B.B.W', '.B.W.', 'B.BW.', 'BBW.W', '..W..'], 'B', 2, 4], [['B.B.W', '.B.W.', 'B.BWB', 'BBW.W', '..W..'], 0]], [[['B.B.W', '.B.W.', 'B.BW.', 'BBW.W', '..W..'], 'B', 3, 2], ['illegal', 'occupied']], [[['W....', '.....', '.....', '.....', '....B'], 'W', 4, 1], [['W....', '.....', '.....', '.....', '.W..B'], 0]], [[['.W.', 'WBW', 'BWB'], 'B', 0, 2], [['.WB', 'WB.', 'BWB'], 1]], [[['BWB', 'W.W', 'BWB'], 'W', 1, 1], ['illegal', 'suicide']]], [[[['W....', '.....', '.....', '.....', '....B'], 'W', 3, 0], [['W....', '.....', '.....', 'W....', '....B'], 0]], [[['W....', '.....', '.....', '.....', '....B'], 'W', 4, 0], [['W....', '.....', '.....', '.....', 'W...B'], 0]], [[['W....', '.....', '.....', '.....', '....B'], 'B', 4, 4], ['illegal', 'occupied']], [[['.W.B.', 'W.WB.', '.WB..', 'WB...', 'B....'], 'W', 0, 2], [['.WWB.', 'W.WB.', '.WB..', 'WB...', 'B....'], 0]], [[['.W.B.', 'W.WB.', '.WB..', 'WB...', 'B....'], 'W', 0, 0], [['WW.B.', 'W.WB.', '.WB..', 'WB...', 'B....'], 0]], [[['.W.B.', 'W.WB.', '.WB..', 'WB...', 'B....'], 'B', 2, 4], [['.W.B.', 'W.WB.', '.WB.B', 'WB...', 'B....'], 0]], [[['WWW', 'W.W', 'WWW'], 'W', 1, 1], ['illegal', 'suicide']], [[['BWB', 'W.W', 'BWB'], 'B', 1, 1], [['B.B', '.B.', 'B.B'], 4]]]]
for i, (args, expected) in enumerate(fixtures[N-1]):
    check("move result 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)

prompt:
Taking the last liberty of an enclosing chain is refused although it would capture.

Input [board, colour, row, col]. Occupied point -> ["illegal", "occupied"]. Otherwise place the stone, remove every adjacent opponent chain left without liberties, then reject the move as ["illegal", "suicide"] only if the placed chain still has no liberty. Return [new_board, captured_stone_count].

split: open-access