FAILURE MAP
← Case archive

FA-70361 / GIS polygon topology / Open access

Right-hand rule ring orientation enforcement: minimum ring size · case 01

Two-vertex closed "rings" pass validation.

Verified by executionVariant 1 · 8 checks per implementationDownload source bundle ↓JSON ↗

ROOT CAUSE

The minimum ring size is 3 positions, admitting a closed segment [a, b, a].

VERIFIED REPAIR

At the minimum ring size step restore `len(ring) < 4 or`, leaving the rest of the model unchanged.

Unsuccessful approach: Using <= 4 rejects valid closed triangles.

Case contract

Input: a polygon as a list of rings (exterior first, then holes), each a list of [x, y] integer positions. Every ring must be closed (first == last) with at least 4 positions, else return None; an empty polygon is None. Exterior rings are made counter-clockwise and holes clockwise by twice-signed-area sign; a reversed ring keeps its start vertex. Zero-area rings are left untouched. Return the rewritten rings.

Why this case matters

GeoJSON writers and vector-tile encoders must emit exterior and hole rings with opposite orientation; renderers use it to decide which rings cut holes.

1 / The failure

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(x):
    rings = x
    if not rings:
        return None
    out = []
    for i, ring in enumerate(rings):
        if len(ring) < 3 or ring[0] != ring[-1]:
            return None
        a2 = 0
        for p, q in zip(ring, ring[1:]):
            a2 += p[0] * q[1] - q[0] * p[1]
        want_ccw = i == 0
        if a2 != 0 and (a2 > 0) != want_ccw:
            ring = [ring[0]] + ring[-2:0:-1] + [ring[0]]
        out.append(ring)
    return out
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('control #0', [[[63, -23], [55, -40], [70, -48], [-53, -42], [-62, -56], [-88, -26], [56, 38], [63, -23]], [[-10, -10], [-10, -4], [-6, -4], [-6, -10], [-10, -10]], [[-4, -10], [0, -10], [0, -4], [-4, -4], [-4, -10]], [[2, -10], [2, -4], [6, -4], [6, -10], [2, -10]]], [[[63, -23], [56, 38], [-88, -26], [-62, -56], [-53, -42], [70, -48], [55, -40], [63, -23]], [[-10, -10], [-10, -4], [-6, -4], [-6, -10], [-10, -10]], [[-4, -10], [-4, -4], [0, -4], [0, -10], [-4, -10]], [[2, -10], [2, -4], [6, -4], [6, -10], [2, -10]]]), ('control #1', [[[53, -16], [50, -21], [-19, 64], [42, 44], [53, -16]], [[-10, -10], [-10, -4], [-6, -4], [-6, -10], [-10, -10]], [[-4, -10], [-4, -4], [0, -4], [0, -10], [-4, -10]]], [[[53, -16], [42, 44], [-19, 64], [50, -21], [53, -16]], [[-10, -10], [-10, -4], [-6, -4], [-6, -10], [-10, -10]], [[-4, -10], [-4, -4], [0, -4], [0, -10], [-4, -10]]]), ('control #2', [[[57, -46], [24, -78], [-55, 32], [-12, 64], [57, -46]], [[-10, -10], [-10, -4], [-6, -4], [-6, -10], [-10, -10]], [[-4, -10], [0, -10], [0, -4], [-4, -4], [-4, -10]], [[2, -10], [6, -10], [6, -4], [2, -4], [2, -10]]], [[[57, -46], [-12, 64], [-55, 32], [24, -78], [57, -46]], [[-10, -10], [-10, -4], [-6, -4], [-6, -10], [-10, -10]], [[-4, -10], [-4, -4], [0, -4], [0, -10], [-4, -10]], [[2, -10], [2, -4], [6, -4], [6, -10], [2, -10]]]), ('control #3', [[[-15, -68], [-15, -80], [-18, -70], [-14, 65], [-8, 57], [53, 44], [50, 23], [-15, -68]]], [[[-15, -68], [50, 23], [53, 44], [-8, 57], [-14, 65], [-18, -70], [-15, -80], [-15, -68]]]), ('control #4', [[[69, 12], [-70, 38], [-68, -6], [-66, -30], [11, -70], [34, -72], [36, -68], [63, -28], [69, 12]], [[-10, -10], [-10, -4], [-6, -4], [-6, -10], [-10, -10]]], [[[69, 12], [-70, 38], [-68, -6], [-66, -30], [11, -70], [34, -72], [36, -68], [63, -28], [69, 12]], [[-10, -10], [-10, -4], [-6, -4], [-6, -10], [-10, -10]]]), ('control #5', [[[12, -61], [-50, 26], [-57, 29], [-56, 51], [-33, 50], [12, -61]], [[-10, -10], [-6, -10], [-6, -4], [-10, -4], [-10, -10]]], [[[12, -61], [-33, 50], [-56, 51], [-57, 29], [-50, 26], [12, -61]], [[-10, -10], [-10, -4], [-6, -4], [-6, -10], [-10, -10]]]), ('boundary #16', [[[0, 0], [5, 0], [10, 0], [0, 0]]], [[[0, 0], [5, 0], [10, 0], [0, 0]]]), ('boundary #20', [[[0, 0], [4, 0], [0, 0]]], None)], [('control #3', [[[-15, -68], [-15, -80], [-18, -70], [-14, 65], [-8, 57], [53, 44], [50, 23], [-15, -68]]], [[[-15, -68], [50, 23], [53, 44], [-8, 57], [-14, 65], [-18, -70], [-15, -80], [-15, -68]]]), ('control #4', [[[69, 12], [-70, 38], [-68, -6], [-66, -30], [11, -70], [34, -72], [36, -68], [63, -28], [69, 12]], [[-10, -10], [-10, -4], [-6, -4], [-6, -10], [-10, -10]]], [[[69, 12], [-70, 38], [-68, -6], [-66, -30], [11, -70], [34, -72], [36, -68], [63, -28], [69, 12]], [[-10, -10], [-10, -4], [-6, -4], [-6, -10], [-10, -10]]]), ('control #5', [[[12, -61], [-50, 26], [-57, 29], [-56, 51], [-33, 50], [12, -61]], [[-10, -10], [-6, -10], [-6, -4], [-10, -4], [-10, -10]]], [[[12, -61], [-33, 50], [-56, 51], [-57, 29], [-50, 26], [12, -61]], [[-10, -10], [-10, -4], [-6, -4], [-6, -10], [-10, -10]]]), ('control #6', [[[-58, 10], [-59, 11], [-61, -9], [58, -67], [92, -23], [-58, 10]]], [[[-58, 10], [-59, 11], [-61, -9], [58, -67], [92, -23], [-58, 10]]]), ('control #7', [[[46, -58], [-55, -48], [-69, -60], [-63, -6], [-75, -1], [64, 11], [46, -58]], [[-10, -10], [-10, -4], [-6, -4], [-6, -10], [-10, -10]], [[-4, -10], [-4, -4], [0, -4], [0, -10], [-4, -10]], [[2, -10], [2, -4], [6, -4], [6, -10], [2, -10]]], [[[46, -58], [64, 11], [-75, -1], [-63, -6], [-69, -60], [-55, -48], [46, -58]], [[-10, -10], [-10, -4], [-6, -4], [-6, -10], [-10, -10]], [[-4, -10], [-4, -4], [0, -4], [0, -10], [-4, -10]], [[2, -10], [2, -4], [6, -4], [6, -10], [2, -10]]]), ('control #8', [[[-19, -75], [-53, -81], [-65, -30], [91, 24], [-19, -75]], [[-10, -10], [-6, -10], [-6, -4], [-10, -4], [-10, -10]]], [[[-19, -75], [91, 24], [-65, -30], [-53, -81], [-19, -75]], [[-10, -10], [-10, -4], [-6, -4], [-6, -10], [-10, -10]]]), ('boundary #17', [[[0, 0], [10, 0], [10, 10], [0, 10], [0, 0]], [[1, 1], [3, 3], [5, 5], [1, 1]]], [[[0, 0], [10, 0], [10, 10], [0, 10], [0, 0]], [[1, 1], [3, 3], [5, 5], [1, 1]]]), ('boundary #22', [[[0, 0], [9, 0], [9, 9], [0, 9], [0, 0]], [[1, 1], [1, 2], [1, 1]]], None)], [('control #6', [[[-58, 10], [-59, 11], [-61, -9], [58, -67], [92, -23], [-58, 10]]], [[[-58, 10], [-59, 11], [-61, -9], [58, -67], [92, -23], [-58, 10]]]), ('control #7', [[[46, -58], [-55, -48], [-69, -60], [-63, -6], [-75, -1], [64, 11], [46, -58]], [[-10, -10], [-10, -4], [-6, -4], [-6, -10], [-10, -10]], [[-4, -10], [-4, -4], [0, -4], [0, -10], [-4, -10]], [[2, -10], [2, -4], [6, -4], [6, -10], [2, -10]]], [[[46, -58], [64, 11], [-75, -1], [-63, -6], [-69, -60], [-55, -48], [46, -58]], [[-10, -10], [-10, -4], [-6, -4], [-6, -10], [-10, -10]], [[-4, -10], [-4, -4], [0, -4], [0, -10], [-4, -10]], [[2, -10], [2, -4], [6, -4], [6, -10], [2, -10]]]), ('control #8', [[[-19, -75], [-53, -81], [-65, -30], [91, 24], [-19, -75]], [[-10, -10], [-6, -10], [-6, -4], [-10, -4], [-10, -10]]], [[[-19, -75], [91, 24], [-65, -30], [-53, -81], [-19, -75]], [[-10, -10], [-10, -4], [-6, -4], [-6, -10], [-10, -10]]]), ('control #9', [[[76, 35], [-31, 78], [-27, 53], [15, -82], [55, -64], [59, -16], [53, -4], [76, 35]], [[-10, -10], [-10, -4], [-6, -4], [-6, -10], [-10, -10]], [[-4, -10], [-4, -4], [0, -4], [0, -10], [-4, -10]], [[2, -10], [6, -10], [6, -4], [2, -4], [2, -10]]], [[[76, 35], [-31, 78], [-27, 53], [15, -82], [55, -64], [59, -16], [53, -4], [76, 35]], [[-10, -10], [-10, -4], [-6, -4], [-6, -10], [-10, -10]], [[-4, -10], [-4, -4], [0, -4], [0, -10], [-4, -10]], [[2, -10], [2, -4], [6, -4], [6, -10], [2, -10]]]), ('control #10', [[[96, -2], [-10, -53], [-33, -60], [-57, -50], [-77, -40], [-90, -24], [-81, -5], [87, 6], [96, -2]]], [[[96, -2], [87, 6], [-81, -5], [-90, -24], [-77, -40], [-57, -50], [-33, -60], [-10, -53], [96, -2]]]), ('control #11', [[[-33, 44], [-59, 30], [-32, -51], [-3, -69], [1, -82], [39, -42], [72, -45], [72, -15], [-33, 44]], [[-10, -10], [-6, -10], [-6, -4], [-10, -4], [-10, -10]], [[-4, -10], [-4, -4], [0, -4], [0, -10], [-4, -10]], [[2, -10], [2, -4], [6, -4], [6, -10], [2, -10]]], [[[-33, 44], [-59, 30], [-32, -51], [-3, -69], [1, -82], [39, -42], [72, -45], [72, -15], [-33, 44]], [[-10, -10], [-10, -4], [-6, -4], [-6, -10], [-10, -10]], [[-4, -10], [-4, -4], [0, -4], [0, -10], [-4, -10]], [[2, -10], [2, -4], [6, -4], [6, -10], [2, -10]]]), ('boundary #20', [[[0, 0], [4, 0], [0, 0]]], None), ('boundary #21', [[[0, 0], [4, 0], [4, 4], [0, 0]]], [[[0, 0], [4, 0], [4, 4], [0, 0]]])], [('control #9', [[[76, 35], [-31, 78], [-27, 53], [15, -82], [55, -64], [59, -16], [53, -4], [76, 35]], [[-10, -10], [-10, -4], [-6, -4], [-6, -10], [-10, -10]], [[-4, -10], [-4, -4], [0, -4], [0, -10], [-4, -10]], [[2, -10], [6, -10], [6, -4], [2, -4], [2, -10]]], [[[76, 35], [-31, 78], [-27, 53], [15, -82], [55, -64], [59, -16], [53, -4], [76, 35]], [[-10, -10], [-10, -4], [-6, -4], [-6, -10], [-10, -10]], [[-4, -10], [-4, -4], [0, -4], [0, -10], [-4, -10]], [[2, -10], [2, -4], [6, -4], [6, -10], [2, -10]]]), ('control #10', [[[96, -2], [-10, -53], [-33, -60], [-57, -50], [-77, -40], [-90, -24], [-81, -5], [87, 6], [96, -2]]], [[[96, -2], [87, 6], [-81, -5], [-90, -24], [-77, -40], [-57, -50], [-33, -60], [-10, -53], [96, -2]]]), ('control #11', [[[-33, 44], [-59, 30], [-32, -51], [-3, -69], [1, -82], [39, -42], [72, -45], [72, -15], [-33, 44]], [[-10, -10], [-6, -10], [-6, -4], [-10, -4], [-10, -10]], [[-4, -10], [-4, -4], [0, -4], [0, -10], [-4, -10]], [[2, -10], [2, -4], [6, -4], [6, -10], [2, -10]]], [[[-33, 44], [-59, 30], [-32, -51], [-3, -69], [1, -82], [39, -42], [72, -45], [72, -15], [-33, 44]], [[-10, -10], [-10, -4], [-6, -4], [-6, -10], [-10, -10]], [[-4, -10], [-4, -4], [0, -4], [0, -10], [-4, -10]], [[2, -10], [2, -4], [6, -4], [6, -10], [2, -10]]]), ('control #12', [[[89, 9], [-81, 16], [39, -38], [71, -54], [61, -56], [89, 9]], [[-10, -10], [-10, -4], [-6, -4], [-6, -10], [-10, -10]]], [[[89, 9], [-81, 16], [39, -38], [71, -54], [61, -56], [89, 9]], [[-10, -10], [-10, -4], [-6, -4], [-6, -10], [-10, -10]]]), ('control #13', [[[92, -1], [31, -67], [-68, -40], [-55, 70], [43, 69], [35, 70], [92, -1]], [[-10, -10], [-10, -4], [-6, -4], [-6, -10], [-10, -10]], [[-4, -10], [-4, -4], [0, -4], [0, -10], [-4, -10]]], [[[92, -1], [35, 70], [43, 69], [-55, 70], [-68, -40], [31, -67], [92, -1]], [[-10, -10], [-10, -4], [-6, -4], [-6, -10], [-10, -10]], [[-4, -10], [-4, -4], [0, -4], [0, -10], [-4, -10]]]), ('regression #14', [[[0, 0], [0, 10], [10, 10], [10, 0], [0, 0]], [[2, 2], [4, 2], [4, 4], [2, 4], [2, 2]], [[5, 5], [7, 5], [7, 7], [5, 7], [5, 5]]], [[[0, 0], [10, 0], [10, 10], [0, 10], [0, 0]], [[2, 2], [2, 4], [4, 4], [4, 2], [2, 2]], [[5, 5], [5, 7], [7, 7], [7, 5], [5, 5]]]), ('boundary #16', [[[0, 0], [5, 0], [10, 0], [0, 0]]], [[[0, 0], [5, 0], [10, 0], [0, 0]]]), ('boundary #22', [[[0, 0], [9, 0], [9, 9], [0, 9], [0, 0]], [[1, 1], [1, 2], [1, 1]]], None)], [('control #12', [[[89, 9], [-81, 16], [39, -38], [71, -54], [61, -56], [89, 9]], [[-10, -10], [-10, -4], [-6, -4], [-6, -10], [-10, -10]]], [[[89, 9], [-81, 16], [39, -38], [71, -54], [61, -56], [89, 9]], [[-10, -10], [-10, -4], [-6, -4], [-6, -10], [-10, -10]]]), ('control #13', [[[92, -1], [31, -67], [-68, -40], [-55, 70], [43, 69], [35, 70], [92, -1]], [[-10, -10], [-10, -4], [-6, -4], [-6, -10], [-10, -10]], [[-4, -10], [-4, -4], [0, -4], [0, -10], [-4, -10]]], [[[92, -1], [35, 70], [43, 69], [-55, 70], [-68, -40], [31, -67], [92, -1]], [[-10, -10], [-10, -4], [-6, -4], [-6, -10], [-10, -10]], [[-4, -10], [-4, -4], [0, -4], [0, -10], [-4, -10]]]), ('regression #14', [[[0, 0], [0, 10], [10, 10], [10, 0], [0, 0]], [[2, 2], [4, 2], [4, 4], [2, 4], [2, 2]], [[5, 5], [7, 5], [7, 7], [5, 7], [5, 5]]], [[[0, 0], [10, 0], [10, 10], [0, 10], [0, 0]], [[2, 2], [2, 4], [4, 4], [4, 2], [2, 2]], [[5, 5], [5, 7], [7, 7], [7, 5], [5, 5]]]), ('regression #15', [[[0, 0], [10, 0], [10, 10], [0, 10], [0, 0]], [[2, 2], [2, 4], [4, 4], [4, 2], [2, 2]], [[5, 5], [7, 5], [7, 7], [5, 7], [5, 5]], [[1, 6], [2, 6], [2, 8], [1, 8], [1, 6]]], [[[0, 0], [10, 0], [10, 10], [0, 10], [0, 0]], [[2, 2], [2, 4], [4, 4], [4, 2], [2, 2]], [[5, 5], [5, 7], [7, 7], [7, 5], [5, 5]], [[1, 6], [1, 8], [2, 8], [2, 6], [1, 6]]]), ('boundary #16', [[[0, 0], [5, 0], [10, 0], [0, 0]]], [[[0, 0], [5, 0], [10, 0], [0, 0]]]), ('boundary #17', [[[0, 0], [10, 0], [10, 10], [0, 10], [0, 0]], [[1, 1], [3, 3], [5, 5], [1, 1]]], [[[0, 0], [10, 0], [10, 10], [0, 10], [0, 0]], [[1, 1], [3, 3], [5, 5], [1, 1]]]), ('boundary #18', [[[0, 0], [4, 0], [4, 4], [0, 4]]], None), ('boundary #20', [[[0, 0], [4, 0], [0, 0]]], None)]]
for label, args, expected in fixtures[N-1]:
    check(label, solve(args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
Boundary fixtureActualExpectedOutcome
control #0[[[63, -23], [56, 38], [-88, -26], [-62, -56], [-53, -42], [70, -48], [55, -40], [63, -23]], [[-10, -10], [-10, -4], [-6, -4], [-6, -10], [-10, -10]], [[-4, -10], [-4, -4], [0, -4], [0, -10], [-4, -10]], [[2, -10], [2, -4], [6, -4], [6, -10], [2, -10]]][[[63, -23], [56, 38], [-88, -26], [-62, -56], [-53, -42], [70, -48], [55, -40], [63, -23]], [[-10, -10], [-10, -4], [-6, -4], [-6, -10], [-10, -10]], [[-4, -10], [-4, -4], [0, -4], [0, -10], [-4, -10]], [[2, -10], [2, -4], [6, -4], [6, -10], [2, -10]]]Passed
control #1[[[53, -16], [42, 44], [-19, 64], [50, -21], [53, -16]], [[-10, -10], [-10, -4], [-6, -4], [-6, -10], [-10, -10]], [[-4, -10], [-4, -4], [0, -4], [0, -10], [-4, -10]]][[[53, -16], [42, 44], [-19, 64], [50, -21], [53, -16]], [[-10, -10], [-10, -4], [-6, -4], [-6, -10], [-10, -10]], [[-4, -10], [-4, -4], [0, -4], [0, -10], [-4, -10]]]Passed
control #2[[[57, -46], [-12, 64], [-55, 32], [24, -78], [57, -46]], [[-10, -10], [-10, -4], [-6, -4], [-6, -10], [-10, -10]], [[-4, -10], [-4, -4], [0, -4], [0, -10], [-4, -10]], [[2, -10], [2, -4], [6, -4], [6, -10], [2, -10]]][[[57, -46], [-12, 64], [-55, 32], [24, -78], [57, -46]], [[-10, -10], [-10, -4], [-6, -4], [-6, -10], [-10, -10]], [[-4, -10], [-4, -4], [0, -4], [0, -10], [-4, -10]], [[2, -10], [2, -4], [6, -4], [6, -10], [2, -10]]]Passed
control #3[[[-15, -68], [50, 23], [53, 44], [-8, 57], [-14, 65], [-18, -70], [-15, -80], [-15, -68]]][[[-15, -68], [50, 23], [53, 44], [-8, 57], [-14, 65], [-18, -70], [-15, -80], [-15, -68]]]Passed
control #4[[[69, 12], [-70, 38], [-68, -6], [-66, -30], [11, -70], [34, -72], [36, -68], [63, -28], [69, 12]], [[-10, -10], [-10, -4], [-6, -4], [-6, -10], [-10, -10]]][[[69, 12], [-70, 38], [-68, -6], [-66, -30], [11, -70], [34, -72], [36, -68], [63, -28], [69, 12]], [[-10, -10], [-10, -4], [-6, -4], [-6, -10], [-10, -10]]]Passed
control #5[[[12, -61], [-33, 50], [-56, 51], [-57, 29], [-50, 26], [12, -61]], [[-10, -10], [-10, -4], [-6, -4], [-6, -10], [-10, -10]]][[[12, -61], [-33, 50], [-56, 51], [-57, 29], [-50, 26], [12, -61]], [[-10, -10], [-10, -4], [-6, -4], [-6, -10], [-10, -10]]]Passed
boundary #16[[[0, 0], [5, 0], [10, 0], [0, 0]]][[[0, 0], [5, 0], [10, 0], [0, 0]]]Passed
boundary #20[[[0, 0], [4, 0], [0, 0]]]NoneFailed

SHA-256 / c4a58b07eb0cd56c43e14a6056592e71ecdc8985aa7acc5f025bd78bbd265ba3

2 / The unsuccessful fix

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(x):
    rings = x
    if not rings:
        return None
    out = []
    for i, ring in enumerate(rings):
        if len(ring) <= 4 or ring[0] != ring[-1]:
            return None
        a2 = 0
        for p, q in zip(ring, ring[1:]):
            a2 += p[0] * q[1] - q[0] * p[1]
        want_ccw = i == 0
        if a2 != 0 and (a2 > 0) != want_ccw:
            ring = [ring[0]] + ring[-2:0:-1] + [ring[0]]
        out.append(ring)
    return out
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('control #0', [[[63, -23], [55, -40], [70, -48], [-53, -42], [-62, -56], [-88, -26], [56, 38], [63, -23]], [[-10, -10], [-10, -4], [-6, -4], [-6, -10], [-10, -10]], [[-4, -10], [0, -10], [0, -4], [-4, -4], [-4, -10]], [[2, -10], [2, -4], [6, -4], [6, -10], [2, -10]]], [[[63, -23], [56, 38], [-88, -26], [-62, -56], [-53, -42], [70, -48], [55, -40], [63, -23]], [[-10, -10], [-10, -4], [-6, -4], [-6, -10], [-10, -10]], [[-4, -10], [-4, -4], [0, -4], [0, -10], [-4, -10]], [[2, -10], [2, -4], [6, -4], [6, -10], [2, -10]]]), ('control #1', [[[53, -16], [50, -21], [-19, 64], [42, 44], [53, -16]], [[-10, -10], [-10, -4], [-6, -4], [-6, -10], [-10, -10]], [[-4, -10], [-4, -4], [0, -4], [0, -10], [-4, -10]]], [[[53, -16], [42, 44], [-19, 64], [50, -21], [53, -16]], [[-10, -10], [-10, -4], [-6, -4], [-6, -10], [-10, -10]], [[-4, -10], [-4, -4], [0, -4], [0, -10], [-4, -10]]]), ('control #2', [[[57, -46], [24, -78], [-55, 32], [-12, 64], [57, -46]], [[-10, -10], [-10, -4], [-6, -4], [-6, -10], [-10, -10]], [[-4, -10], [0, -10], [0, -4], [-4, -4], [-4, -10]], [[2, -10], [6, -10], [6, -4], [2, -4], [2, -10]]], [[[57, -46], [-12, 64], [-55, 32], [24, -78], [57, -46]], [[-10, -10], [-10, -4], [-6, -4], [-6, -10], [-10, -10]], [[-4, -10], [-4, -4], [0, -4], [0, -10], [-4, -10]], [[2, -10], [2, -4], [6, -4], [6, -10], [2, -10]]]), ('control #3', [[[-15, -68], [-15, -80], [-18, -70], [-14, 65], [-8, 57], [53, 44], [50, 23], [-15, -68]]], [[[-15, -68], [50, 23], [53, 44], [-8, 57], [-14, 65], [-18, -70], [-15, -80], [-15, -68]]]), ('control #4', [[[69, 12], [-70, 38], [-68, -6], [-66, -30], [11, -70], [34, -72], [36, -68], [63, -28], [69, 12]], [[-10, -10], [-10, -4], [-6, -4], [-6, -10], [-10, -10]]], [[[69, 12], [-70, 38], [-68, -6], [-66, -30], [11, -70], [34, -72], [36, -68], [63, -28], [69, 12]], [[-10, -10], [-10, -4], [-6, -4], [-6, -10], [-10, -10]]]), ('control #5', [[[12, -61], [-50, 26], [-57, 29], [-56, 51], [-33, 50], [12, -61]], [[-10, -10], [-6, -10], [-6, -4], [-10, -4], [-10, -10]]], [[[12, -61], [-33, 50], [-56, 51], [-57, 29], [-50, 26], [12, -61]], [[-10, -10], [-10, -4], [-6, -4], [-6, -10], [-10, -10]]]), ('boundary #16', [[[0, 0], [5, 0], [10, 0], [0, 0]]], [[[0, 0], [5, 0], [10, 0], [0, 0]]]), ('boundary #20', [[[0, 0], [4, 0], [0, 0]]], None)], [('control #3', [[[-15, -68], [-15, -80], [-18, -70], [-14, 65], [-8, 57], [53, 44], [50, 23], [-15, -68]]], [[[-15, -68], [50, 23], [53, 44], [-8, 57], [-14, 65], [-18, -70], [-15, -80], [-15, -68]]]), ('control #4', [[[69, 12], [-70, 38], [-68, -6], [-66, -30], [11, -70], [34, -72], [36, -68], [63, -28], [69, 12]], [[-10, -10], [-10, -4], [-6, -4], [-6, -10], [-10, -10]]], [[[69, 12], [-70, 38], [-68, -6], [-66, -30], [11, -70], [34, -72], [36, -68], [63, -28], [69, 12]], [[-10, -10], [-10, -4], [-6, -4], [-6, -10], [-10, -10]]]), ('control #5', [[[12, -61], [-50, 26], [-57, 29], [-56, 51], [-33, 50], [12, -61]], [[-10, -10], [-6, -10], [-6, -4], [-10, -4], [-10, -10]]], [[[12, -61], [-33, 50], [-56, 51], [-57, 29], [-50, 26], [12, -61]], [[-10, -10], [-10, -4], [-6, -4], [-6, -10], [-10, -10]]]), ('control #6', [[[-58, 10], [-59, 11], [-61, -9], [58, -67], [92, -23], [-58, 10]]], [[[-58, 10], [-59, 11], [-61, -9], [58, -67], [92, -23], [-58, 10]]]), ('control #7', [[[46, -58], [-55, -48], [-69, -60], [-63, -6], [-75, -1], [64, 11], [46, -58]], [[-10, -10], [-10, -4], [-6, -4], [-6, -10], [-10, -10]], [[-4, -10], [-4, -4], [0, -4], [0, -10], [-4, -10]], [[2, -10], [2, -4], [6, -4], [6, -10], [2, -10]]], [[[46, -58], [64, 11], [-75, -1], [-63, -6], [-69, -60], [-55, -48], [46, -58]], [[-10, -10], [-10, -4], [-6, -4], [-6, -10], [-10, -10]], [[-4, -10], [-4, -4], [0, -4], [0, -10], [-4, -10]], [[2, -10], [2, -4], [6, -4], [6, -10], [2, -10]]]), ('control #8', [[[-19, -75], [-53, -81], [-65, -30], [91, 24], [-19, -75]], [[-10, -10], [-6, -10], [-6, -4], [-10, -4], [-10, -10]]], [[[-19, -75], [91, 24], [-65, -30], [-53, -81], [-19, -75]], [[-10, -10], [-10, -4], [-6, -4], [-6, -10], [-10, -10]]]), ('boundary #17', [[[0, 0], [10, 0], [10, 10], [0, 10], [0, 0]], [[1, 1], [3, 3], [5, 5], [1, 1]]], [[[0, 0], [10, 0], [10, 10], [0, 10], [0, 0]], [[1, 1], [3, 3], [5, 5], [1, 1]]]), ('boundary #22', [[[0, 0], [9, 0], [9, 9], [0, 9], [0, 0]], [[1, 1], [1, 2], [1, 1]]], None)], [('control #6', [[[-58, 10], [-59, 11], [-61, -9], [58, -67], [92, -23], [-58, 10]]], [[[-58, 10], [-59, 11], [-61, -9], [58, -67], [92, -23], [-58, 10]]]), ('control #7', [[[46, -58], [-55, -48], [-69, -60], [-63, -6], [-75, -1], [64, 11], [46, -58]], [[-10, -10], [-10, -4], [-6, -4], [-6, -10], [-10, -10]], [[-4, -10], [-4, -4], [0, -4], [0, -10], [-4, -10]], [[2, -10], [2, -4], [6, -4], [6, -10], [2, -10]]], [[[46, -58], [64, 11], [-75, -1], [-63, -6], [-69, -60], [-55, -48], [46, -58]], [[-10, -10], [-10, -4], [-6, -4], [-6, -10], [-10, -10]], [[-4, -10], [-4, -4], [0, -4], [0, -10], [-4, -10]], [[2, -10], [2, -4], [6, -4], [6, -10], [2, -10]]]), ('control #8', [[[-19, -75], [-53, -81], [-65, -30], [91, 24], [-19, -75]], [[-10, -10], [-6, -10], [-6, -4], [-10, -4], [-10, -10]]], [[[-19, -75], [91, 24], [-65, -30], [-53, -81], [-19, -75]], [[-10, -10], [-10, -4], [-6, -4], [-6, -10], [-10, -10]]]), ('control #9', [[[76, 35], [-31, 78], [-27, 53], [15, -82], [55, -64], [59, -16], [53, -4], [76, 35]], [[-10, -10], [-10, -4], [-6, -4], [-6, -10], [-10, -10]], [[-4, -10], [-4, -4], [0, -4], [0, -10], [-4, -10]], [[2, -10], [6, -10], [6, -4], [2, -4], [2, -10]]], [[[76, 35], [-31, 78], [-27, 53], [15, -82], [55, -64], [59, -16], [53, -4], [76, 35]], [[-10, -10], [-10, -4], [-6, -4], [-6, -10], [-10, -10]], [[-4, -10], [-4, -4], [0, -4], [0, -10], [-4, -10]], [[2, -10], [2, -4], [6, -4], [6, -10], [2, -10]]]), ('control #10', [[[96, -2], [-10, -53], [-33, -60], [-57, -50], [-77, -40], [-90, -24], [-81, -5], [87, 6], [96, -2]]], [[[96, -2], [87, 6], [-81, -5], [-90, -24], [-77, -40], [-57, -50], [-33, -60], [-10, -53], [96, -2]]]), ('control #11', [[[-33, 44], [-59, 30], [-32, -51], [-3, -69], [1, -82], [39, -42], [72, -45], [72, -15], [-33, 44]], [[-10, -10], [-6, -10], [-6, -4], [-10, -4], [-10, -10]], [[-4, -10], [-4, -4], [0, -4], [0, -10], [-4, -10]], [[2, -10], [2, -4], [6, -4], [6, -10], [2, -10]]], [[[-33, 44], [-59, 30], [-32, -51], [-3, -69], [1, -82], [39, -42], [72, -45], [72, -15], [-33, 44]], [[-10, -10], [-10, -4], [-6, -4], [-6, -10], [-10, -10]], [[-4, -10], [-4, -4], [0, -4], [0, -10], [-4, -10]], [[2, -10], [2, -4], [6, -4], [6, -10], [2, -10]]]), ('boundary #20', [[[0, 0], [4, 0], [0, 0]]], None), ('boundary #21', [[[0, 0], [4, 0], [4, 4], [0, 0]]], [[[0, 0], [4, 0], [4, 4], [0, 0]]])], [('control #9', [[[76, 35], [-31, 78], [-27, 53], [15, -82], [55, -64], [59, -16], [53, -4], [76, 35]], [[-10, -10], [-10, -4], [-6, -4], [-6, -10], [-10, -10]], [[-4, -10], [-4, -4], [0, -4], [0, -10], [-4, -10]], [[2, -10], [6, -10], [6, -4], [2, -4], [2, -10]]], [[[76, 35], [-31, 78], [-27, 53], [15, -82], [55, -64], [59, -16], [53, -4], [76, 35]], [[-10, -10], [-10, -4], [-6, -4], [-6, -10], [-10, -10]], [[-4, -10], [-4, -4], [0, -4], [0, -10], [-4, -10]], [[2, -10], [2, -4], [6, -4], [6, -10], [2, -10]]]), ('control #10', [[[96, -2], [-10, -53], [-33, -60], [-57, -50], [-77, -40], [-90, -24], [-81, -5], [87, 6], [96, -2]]], [[[96, -2], [87, 6], [-81, -5], [-90, -24], [-77, -40], [-57, -50], [-33, -60], [-10, -53], [96, -2]]]), ('control #11', [[[-33, 44], [-59, 30], [-32, -51], [-3, -69], [1, -82], [39, -42], [72, -45], [72, -15], [-33, 44]], [[-10, -10], [-6, -10], [-6, -4], [-10, -4], [-10, -10]], [[-4, -10], [-4, -4], [0, -4], [0, -10], [-4, -10]], [[2, -10], [2, -4], [6, -4], [6, -10], [2, -10]]], [[[-33, 44], [-59, 30], [-32, -51], [-3, -69], [1, -82], [39, -42], [72, -45], [72, -15], [-33, 44]], [[-10, -10], [-10, -4], [-6, -4], [-6, -10], [-10, -10]], [[-4, -10], [-4, -4], [0, -4], [0, -10], [-4, -10]], [[2, -10], [2, -4], [6, -4], [6, -10], [2, -10]]]), ('control #12', [[[89, 9], [-81, 16], [39, -38], [71, -54], [61, -56], [89, 9]], [[-10, -10], [-10, -4], [-6, -4], [-6, -10], [-10, -10]]], [[[89, 9], [-81, 16], [39, -38], [71, -54], [61, -56], [89, 9]], [[-10, -10], [-10, -4], [-6, -4], [-6, -10], [-10, -10]]]), ('control #13', [[[92, -1], [31, -67], [-68, -40], [-55, 70], [43, 69], [35, 70], [92, -1]], [[-10, -10], [-10, -4], [-6, -4], [-6, -10], [-10, -10]], [[-4, -10], [-4, -4], [0, -4], [0, -10], [-4, -10]]], [[[92, -1], [35, 70], [43, 69], [-55, 70], [-68, -40], [31, -67], [92, -1]], [[-10, -10], [-10, -4], [-6, -4], [-6, -10], [-10, -10]], [[-4, -10], [-4, -4], [0, -4], [0, -10], [-4, -10]]]), ('regression #14', [[[0, 0], [0, 10], [10, 10], [10, 0], [0, 0]], [[2, 2], [4, 2], [4, 4], [2, 4], [2, 2]], [[5, 5], [7, 5], [7, 7], [5, 7], [5, 5]]], [[[0, 0], [10, 0], [10, 10], [0, 10], [0, 0]], [[2, 2], [2, 4], [4, 4], [4, 2], [2, 2]], [[5, 5], [5, 7], [7, 7], [7, 5], [5, 5]]]), ('boundary #16', [[[0, 0], [5, 0], [10, 0], [0, 0]]], [[[0, 0], [5, 0], [10, 0], [0, 0]]]), ('boundary #22', [[[0, 0], [9, 0], [9, 9], [0, 9], [0, 0]], [[1, 1], [1, 2], [1, 1]]], None)], [('control #12', [[[89, 9], [-81, 16], [39, -38], [71, -54], [61, -56], [89, 9]], [[-10, -10], [-10, -4], [-6, -4], [-6, -10], [-10, -10]]], [[[89, 9], [-81, 16], [39, -38], [71, -54], [61, -56], [89, 9]], [[-10, -10], [-10, -4], [-6, -4], [-6, -10], [-10, -10]]]), ('control #13', [[[92, -1], [31, -67], [-68, -40], [-55, 70], [43, 69], [35, 70], [92, -1]], [[-10, -10], [-10, -4], [-6, -4], [-6, -10], [-10, -10]], [[-4, -10], [-4, -4], [0, -4], [0, -10], [-4, -10]]], [[[92, -1], [35, 70], [43, 69], [-55, 70], [-68, -40], [31, -67], [92, -1]], [[-10, -10], [-10, -4], [-6, -4], [-6, -10], [-10, -10]], [[-4, -10], [-4, -4], [0, -4], [0, -10], [-4, -10]]]), ('regression #14', [[[0, 0], [0, 10], [10, 10], [10, 0], [0, 0]], [[2, 2], [4, 2], [4, 4], [2, 4], [2, 2]], [[5, 5], [7, 5], [7, 7], [5, 7], [5, 5]]], [[[0, 0], [10, 0], [10, 10], [0, 10], [0, 0]], [[2, 2], [2, 4], [4, 4], [4, 2], [2, 2]], [[5, 5], [5, 7], [7, 7], [7, 5], [5, 5]]]), ('regression #15', [[[0, 0], [10, 0], [10, 10], [0, 10], [0, 0]], [[2, 2], [2, 4], [4, 4], [4, 2], [2, 2]], [[5, 5], [7, 5], [7, 7], [5, 7], [5, 5]], [[1, 6], [2, 6], [2, 8], [1, 8], [1, 6]]], [[[0, 0], [10, 0], [10, 10], [0, 10], [0, 0]], [[2, 2], [2, 4], [4, 4], [4, 2], [2, 2]], [[5, 5], [5, 7], [7, 7], [7, 5], [5, 5]], [[1, 6], [1, 8], [2, 8], [2, 6], [1, 6]]]), ('boundary #16', [[[0, 0], [5, 0], [10, 0], [0, 0]]], [[[0, 0], [5, 0], [10, 0], [0, 0]]]), ('boundary #17', [[[0, 0], [10, 0], [10, 10], [0, 10], [0, 0]], [[1, 1], [3, 3], [5, 5], [1, 1]]], [[[0, 0], [10, 0], [10, 10], [0, 10], [0, 0]], [[1, 1], [3, 3], [5, 5], [1, 1]]]), ('boundary #18', [[[0, 0], [4, 0], [4, 4], [0, 4]]], None), ('boundary #20', [[[0, 0], [4, 0], [0, 0]]], None)]]
for label, args, expected in fixtures[N-1]:
    check(label, solve(args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
Boundary fixtureActualExpectedOutcome
control #0[[[63, -23], [56, 38], [-88, -26], [-62, -56], [-53, -42], [70, -48], [55, -40], [63, -23]], [[-10, -10], [-10, -4], [-6, -4], [-6, -10], [-10, -10]], [[-4, -10], [-4, -4], [0, -4], [0, -10], [-4, -10]], [[2, -10], [2, -4], [6, -4], [6, -10], [2, -10]]][[[63, -23], [56, 38], [-88, -26], [-62, -56], [-53, -42], [70, -48], [55, -40], [63, -23]], [[-10, -10], [-10, -4], [-6, -4], [-6, -10], [-10, -10]], [[-4, -10], [-4, -4], [0, -4], [0, -10], [-4, -10]], [[2, -10], [2, -4], [6, -4], [6, -10], [2, -10]]]Passed
control #1[[[53, -16], [42, 44], [-19, 64], [50, -21], [53, -16]], [[-10, -10], [-10, -4], [-6, -4], [-6, -10], [-10, -10]], [[-4, -10], [-4, -4], [0, -4], [0, -10], [-4, -10]]][[[53, -16], [42, 44], [-19, 64], [50, -21], [53, -16]], [[-10, -10], [-10, -4], [-6, -4], [-6, -10], [-10, -10]], [[-4, -10], [-4, -4], [0, -4], [0, -10], [-4, -10]]]Passed
control #2[[[57, -46], [-12, 64], [-55, 32], [24, -78], [57, -46]], [[-10, -10], [-10, -4], [-6, -4], [-6, -10], [-10, -10]], [[-4, -10], [-4, -4], [0, -4], [0, -10], [-4, -10]], [[2, -10], [2, -4], [6, -4], [6, -10], [2, -10]]][[[57, -46], [-12, 64], [-55, 32], [24, -78], [57, -46]], [[-10, -10], [-10, -4], [-6, -4], [-6, -10], [-10, -10]], [[-4, -10], [-4, -4], [0, -4], [0, -10], [-4, -10]], [[2, -10], [2, -4], [6, -4], [6, -10], [2, -10]]]Passed
control #3[[[-15, -68], [50, 23], [53, 44], [-8, 57], [-14, 65], [-18, -70], [-15, -80], [-15, -68]]][[[-15, -68], [50, 23], [53, 44], [-8, 57], [-14, 65], [-18, -70], [-15, -80], [-15, -68]]]Passed
control #4[[[69, 12], [-70, 38], [-68, -6], [-66, -30], [11, -70], [34, -72], [36, -68], [63, -28], [69, 12]], [[-10, -10], [-10, -4], [-6, -4], [-6, -10], [-10, -10]]][[[69, 12], [-70, 38], [-68, -6], [-66, -30], [11, -70], [34, -72], [36, -68], [63, -28], [69, 12]], [[-10, -10], [-10, -4], [-6, -4], [-6, -10], [-10, -10]]]Passed
control #5[[[12, -61], [-33, 50], [-56, 51], [-57, 29], [-50, 26], [12, -61]], [[-10, -10], [-10, -4], [-6, -4], [-6, -10], [-10, -10]]][[[12, -61], [-33, 50], [-56, 51], [-57, 29], [-50, 26], [12, -61]], [[-10, -10], [-10, -4], [-6, -4], [-6, -10], [-10, -10]]]Passed
boundary #16None[[[0, 0], [5, 0], [10, 0], [0, 0]]]Failed
boundary #20NoneNonePassed

SHA-256 / ee02d9209bc6184bfb8949c08249044c9c6800bf9fc395ad930a51ce9dbee2a1

3 / The verified repair

Exit 0
"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(x):
    rings = x
    if not rings:
        return None
    out = []
    for i, ring in enumerate(rings):
        if len(ring) < 4 or ring[0] != ring[-1]:
            return None
        a2 = 0
        for p, q in zip(ring, ring[1:]):
            a2 += p[0] * q[1] - q[0] * p[1]
        want_ccw = i == 0
        if a2 != 0 and (a2 > 0) != want_ccw:
            ring = [ring[0]] + ring[-2:0:-1] + [ring[0]]
        out.append(ring)
    return out
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('control #0', [[[63, -23], [55, -40], [70, -48], [-53, -42], [-62, -56], [-88, -26], [56, 38], [63, -23]], [[-10, -10], [-10, -4], [-6, -4], [-6, -10], [-10, -10]], [[-4, -10], [0, -10], [0, -4], [-4, -4], [-4, -10]], [[2, -10], [2, -4], [6, -4], [6, -10], [2, -10]]], [[[63, -23], [56, 38], [-88, -26], [-62, -56], [-53, -42], [70, -48], [55, -40], [63, -23]], [[-10, -10], [-10, -4], [-6, -4], [-6, -10], [-10, -10]], [[-4, -10], [-4, -4], [0, -4], [0, -10], [-4, -10]], [[2, -10], [2, -4], [6, -4], [6, -10], [2, -10]]]), ('control #1', [[[53, -16], [50, -21], [-19, 64], [42, 44], [53, -16]], [[-10, -10], [-10, -4], [-6, -4], [-6, -10], [-10, -10]], [[-4, -10], [-4, -4], [0, -4], [0, -10], [-4, -10]]], [[[53, -16], [42, 44], [-19, 64], [50, -21], [53, -16]], [[-10, -10], [-10, -4], [-6, -4], [-6, -10], [-10, -10]], [[-4, -10], [-4, -4], [0, -4], [0, -10], [-4, -10]]]), ('control #2', [[[57, -46], [24, -78], [-55, 32], [-12, 64], [57, -46]], [[-10, -10], [-10, -4], [-6, -4], [-6, -10], [-10, -10]], [[-4, -10], [0, -10], [0, -4], [-4, -4], [-4, -10]], [[2, -10], [6, -10], [6, -4], [2, -4], [2, -10]]], [[[57, -46], [-12, 64], [-55, 32], [24, -78], [57, -46]], [[-10, -10], [-10, -4], [-6, -4], [-6, -10], [-10, -10]], [[-4, -10], [-4, -4], [0, -4], [0, -10], [-4, -10]], [[2, -10], [2, -4], [6, -4], [6, -10], [2, -10]]]), ('control #3', [[[-15, -68], [-15, -80], [-18, -70], [-14, 65], [-8, 57], [53, 44], [50, 23], [-15, -68]]], [[[-15, -68], [50, 23], [53, 44], [-8, 57], [-14, 65], [-18, -70], [-15, -80], [-15, -68]]]), ('control #4', [[[69, 12], [-70, 38], [-68, -6], [-66, -30], [11, -70], [34, -72], [36, -68], [63, -28], [69, 12]], [[-10, -10], [-10, -4], [-6, -4], [-6, -10], [-10, -10]]], [[[69, 12], [-70, 38], [-68, -6], [-66, -30], [11, -70], [34, -72], [36, -68], [63, -28], [69, 12]], [[-10, -10], [-10, -4], [-6, -4], [-6, -10], [-10, -10]]]), ('control #5', [[[12, -61], [-50, 26], [-57, 29], [-56, 51], [-33, 50], [12, -61]], [[-10, -10], [-6, -10], [-6, -4], [-10, -4], [-10, -10]]], [[[12, -61], [-33, 50], [-56, 51], [-57, 29], [-50, 26], [12, -61]], [[-10, -10], [-10, -4], [-6, -4], [-6, -10], [-10, -10]]]), ('boundary #16', [[[0, 0], [5, 0], [10, 0], [0, 0]]], [[[0, 0], [5, 0], [10, 0], [0, 0]]]), ('boundary #20', [[[0, 0], [4, 0], [0, 0]]], None)], [('control #3', [[[-15, -68], [-15, -80], [-18, -70], [-14, 65], [-8, 57], [53, 44], [50, 23], [-15, -68]]], [[[-15, -68], [50, 23], [53, 44], [-8, 57], [-14, 65], [-18, -70], [-15, -80], [-15, -68]]]), ('control #4', [[[69, 12], [-70, 38], [-68, -6], [-66, -30], [11, -70], [34, -72], [36, -68], [63, -28], [69, 12]], [[-10, -10], [-10, -4], [-6, -4], [-6, -10], [-10, -10]]], [[[69, 12], [-70, 38], [-68, -6], [-66, -30], [11, -70], [34, -72], [36, -68], [63, -28], [69, 12]], [[-10, -10], [-10, -4], [-6, -4], [-6, -10], [-10, -10]]]), ('control #5', [[[12, -61], [-50, 26], [-57, 29], [-56, 51], [-33, 50], [12, -61]], [[-10, -10], [-6, -10], [-6, -4], [-10, -4], [-10, -10]]], [[[12, -61], [-33, 50], [-56, 51], [-57, 29], [-50, 26], [12, -61]], [[-10, -10], [-10, -4], [-6, -4], [-6, -10], [-10, -10]]]), ('control #6', [[[-58, 10], [-59, 11], [-61, -9], [58, -67], [92, -23], [-58, 10]]], [[[-58, 10], [-59, 11], [-61, -9], [58, -67], [92, -23], [-58, 10]]]), ('control #7', [[[46, -58], [-55, -48], [-69, -60], [-63, -6], [-75, -1], [64, 11], [46, -58]], [[-10, -10], [-10, -4], [-6, -4], [-6, -10], [-10, -10]], [[-4, -10], [-4, -4], [0, -4], [0, -10], [-4, -10]], [[2, -10], [2, -4], [6, -4], [6, -10], [2, -10]]], [[[46, -58], [64, 11], [-75, -1], [-63, -6], [-69, -60], [-55, -48], [46, -58]], [[-10, -10], [-10, -4], [-6, -4], [-6, -10], [-10, -10]], [[-4, -10], [-4, -4], [0, -4], [0, -10], [-4, -10]], [[2, -10], [2, -4], [6, -4], [6, -10], [2, -10]]]), ('control #8', [[[-19, -75], [-53, -81], [-65, -30], [91, 24], [-19, -75]], [[-10, -10], [-6, -10], [-6, -4], [-10, -4], [-10, -10]]], [[[-19, -75], [91, 24], [-65, -30], [-53, -81], [-19, -75]], [[-10, -10], [-10, -4], [-6, -4], [-6, -10], [-10, -10]]]), ('boundary #17', [[[0, 0], [10, 0], [10, 10], [0, 10], [0, 0]], [[1, 1], [3, 3], [5, 5], [1, 1]]], [[[0, 0], [10, 0], [10, 10], [0, 10], [0, 0]], [[1, 1], [3, 3], [5, 5], [1, 1]]]), ('boundary #22', [[[0, 0], [9, 0], [9, 9], [0, 9], [0, 0]], [[1, 1], [1, 2], [1, 1]]], None)], [('control #6', [[[-58, 10], [-59, 11], [-61, -9], [58, -67], [92, -23], [-58, 10]]], [[[-58, 10], [-59, 11], [-61, -9], [58, -67], [92, -23], [-58, 10]]]), ('control #7', [[[46, -58], [-55, -48], [-69, -60], [-63, -6], [-75, -1], [64, 11], [46, -58]], [[-10, -10], [-10, -4], [-6, -4], [-6, -10], [-10, -10]], [[-4, -10], [-4, -4], [0, -4], [0, -10], [-4, -10]], [[2, -10], [2, -4], [6, -4], [6, -10], [2, -10]]], [[[46, -58], [64, 11], [-75, -1], [-63, -6], [-69, -60], [-55, -48], [46, -58]], [[-10, -10], [-10, -4], [-6, -4], [-6, -10], [-10, -10]], [[-4, -10], [-4, -4], [0, -4], [0, -10], [-4, -10]], [[2, -10], [2, -4], [6, -4], [6, -10], [2, -10]]]), ('control #8', [[[-19, -75], [-53, -81], [-65, -30], [91, 24], [-19, -75]], [[-10, -10], [-6, -10], [-6, -4], [-10, -4], [-10, -10]]], [[[-19, -75], [91, 24], [-65, -30], [-53, -81], [-19, -75]], [[-10, -10], [-10, -4], [-6, -4], [-6, -10], [-10, -10]]]), ('control #9', [[[76, 35], [-31, 78], [-27, 53], [15, -82], [55, -64], [59, -16], [53, -4], [76, 35]], [[-10, -10], [-10, -4], [-6, -4], [-6, -10], [-10, -10]], [[-4, -10], [-4, -4], [0, -4], [0, -10], [-4, -10]], [[2, -10], [6, -10], [6, -4], [2, -4], [2, -10]]], [[[76, 35], [-31, 78], [-27, 53], [15, -82], [55, -64], [59, -16], [53, -4], [76, 35]], [[-10, -10], [-10, -4], [-6, -4], [-6, -10], [-10, -10]], [[-4, -10], [-4, -4], [0, -4], [0, -10], [-4, -10]], [[2, -10], [2, -4], [6, -4], [6, -10], [2, -10]]]), ('control #10', [[[96, -2], [-10, -53], [-33, -60], [-57, -50], [-77, -40], [-90, -24], [-81, -5], [87, 6], [96, -2]]], [[[96, -2], [87, 6], [-81, -5], [-90, -24], [-77, -40], [-57, -50], [-33, -60], [-10, -53], [96, -2]]]), ('control #11', [[[-33, 44], [-59, 30], [-32, -51], [-3, -69], [1, -82], [39, -42], [72, -45], [72, -15], [-33, 44]], [[-10, -10], [-6, -10], [-6, -4], [-10, -4], [-10, -10]], [[-4, -10], [-4, -4], [0, -4], [0, -10], [-4, -10]], [[2, -10], [2, -4], [6, -4], [6, -10], [2, -10]]], [[[-33, 44], [-59, 30], [-32, -51], [-3, -69], [1, -82], [39, -42], [72, -45], [72, -15], [-33, 44]], [[-10, -10], [-10, -4], [-6, -4], [-6, -10], [-10, -10]], [[-4, -10], [-4, -4], [0, -4], [0, -10], [-4, -10]], [[2, -10], [2, -4], [6, -4], [6, -10], [2, -10]]]), ('boundary #20', [[[0, 0], [4, 0], [0, 0]]], None), ('boundary #21', [[[0, 0], [4, 0], [4, 4], [0, 0]]], [[[0, 0], [4, 0], [4, 4], [0, 0]]])], [('control #9', [[[76, 35], [-31, 78], [-27, 53], [15, -82], [55, -64], [59, -16], [53, -4], [76, 35]], [[-10, -10], [-10, -4], [-6, -4], [-6, -10], [-10, -10]], [[-4, -10], [-4, -4], [0, -4], [0, -10], [-4, -10]], [[2, -10], [6, -10], [6, -4], [2, -4], [2, -10]]], [[[76, 35], [-31, 78], [-27, 53], [15, -82], [55, -64], [59, -16], [53, -4], [76, 35]], [[-10, -10], [-10, -4], [-6, -4], [-6, -10], [-10, -10]], [[-4, -10], [-4, -4], [0, -4], [0, -10], [-4, -10]], [[2, -10], [2, -4], [6, -4], [6, -10], [2, -10]]]), ('control #10', [[[96, -2], [-10, -53], [-33, -60], [-57, -50], [-77, -40], [-90, -24], [-81, -5], [87, 6], [96, -2]]], [[[96, -2], [87, 6], [-81, -5], [-90, -24], [-77, -40], [-57, -50], [-33, -60], [-10, -53], [96, -2]]]), ('control #11', [[[-33, 44], [-59, 30], [-32, -51], [-3, -69], [1, -82], [39, -42], [72, -45], [72, -15], [-33, 44]], [[-10, -10], [-6, -10], [-6, -4], [-10, -4], [-10, -10]], [[-4, -10], [-4, -4], [0, -4], [0, -10], [-4, -10]], [[2, -10], [2, -4], [6, -4], [6, -10], [2, -10]]], [[[-33, 44], [-59, 30], [-32, -51], [-3, -69], [1, -82], [39, -42], [72, -45], [72, -15], [-33, 44]], [[-10, -10], [-10, -4], [-6, -4], [-6, -10], [-10, -10]], [[-4, -10], [-4, -4], [0, -4], [0, -10], [-4, -10]], [[2, -10], [2, -4], [6, -4], [6, -10], [2, -10]]]), ('control #12', [[[89, 9], [-81, 16], [39, -38], [71, -54], [61, -56], [89, 9]], [[-10, -10], [-10, -4], [-6, -4], [-6, -10], [-10, -10]]], [[[89, 9], [-81, 16], [39, -38], [71, -54], [61, -56], [89, 9]], [[-10, -10], [-10, -4], [-6, -4], [-6, -10], [-10, -10]]]), ('control #13', [[[92, -1], [31, -67], [-68, -40], [-55, 70], [43, 69], [35, 70], [92, -1]], [[-10, -10], [-10, -4], [-6, -4], [-6, -10], [-10, -10]], [[-4, -10], [-4, -4], [0, -4], [0, -10], [-4, -10]]], [[[92, -1], [35, 70], [43, 69], [-55, 70], [-68, -40], [31, -67], [92, -1]], [[-10, -10], [-10, -4], [-6, -4], [-6, -10], [-10, -10]], [[-4, -10], [-4, -4], [0, -4], [0, -10], [-4, -10]]]), ('regression #14', [[[0, 0], [0, 10], [10, 10], [10, 0], [0, 0]], [[2, 2], [4, 2], [4, 4], [2, 4], [2, 2]], [[5, 5], [7, 5], [7, 7], [5, 7], [5, 5]]], [[[0, 0], [10, 0], [10, 10], [0, 10], [0, 0]], [[2, 2], [2, 4], [4, 4], [4, 2], [2, 2]], [[5, 5], [5, 7], [7, 7], [7, 5], [5, 5]]]), ('boundary #16', [[[0, 0], [5, 0], [10, 0], [0, 0]]], [[[0, 0], [5, 0], [10, 0], [0, 0]]]), ('boundary #22', [[[0, 0], [9, 0], [9, 9], [0, 9], [0, 0]], [[1, 1], [1, 2], [1, 1]]], None)], [('control #12', [[[89, 9], [-81, 16], [39, -38], [71, -54], [61, -56], [89, 9]], [[-10, -10], [-10, -4], [-6, -4], [-6, -10], [-10, -10]]], [[[89, 9], [-81, 16], [39, -38], [71, -54], [61, -56], [89, 9]], [[-10, -10], [-10, -4], [-6, -4], [-6, -10], [-10, -10]]]), ('control #13', [[[92, -1], [31, -67], [-68, -40], [-55, 70], [43, 69], [35, 70], [92, -1]], [[-10, -10], [-10, -4], [-6, -4], [-6, -10], [-10, -10]], [[-4, -10], [-4, -4], [0, -4], [0, -10], [-4, -10]]], [[[92, -1], [35, 70], [43, 69], [-55, 70], [-68, -40], [31, -67], [92, -1]], [[-10, -10], [-10, -4], [-6, -4], [-6, -10], [-10, -10]], [[-4, -10], [-4, -4], [0, -4], [0, -10], [-4, -10]]]), ('regression #14', [[[0, 0], [0, 10], [10, 10], [10, 0], [0, 0]], [[2, 2], [4, 2], [4, 4], [2, 4], [2, 2]], [[5, 5], [7, 5], [7, 7], [5, 7], [5, 5]]], [[[0, 0], [10, 0], [10, 10], [0, 10], [0, 0]], [[2, 2], [2, 4], [4, 4], [4, 2], [2, 2]], [[5, 5], [5, 7], [7, 7], [7, 5], [5, 5]]]), ('regression #15', [[[0, 0], [10, 0], [10, 10], [0, 10], [0, 0]], [[2, 2], [2, 4], [4, 4], [4, 2], [2, 2]], [[5, 5], [7, 5], [7, 7], [5, 7], [5, 5]], [[1, 6], [2, 6], [2, 8], [1, 8], [1, 6]]], [[[0, 0], [10, 0], [10, 10], [0, 10], [0, 0]], [[2, 2], [2, 4], [4, 4], [4, 2], [2, 2]], [[5, 5], [5, 7], [7, 7], [7, 5], [5, 5]], [[1, 6], [1, 8], [2, 8], [2, 6], [1, 6]]]), ('boundary #16', [[[0, 0], [5, 0], [10, 0], [0, 0]]], [[[0, 0], [5, 0], [10, 0], [0, 0]]]), ('boundary #17', [[[0, 0], [10, 0], [10, 10], [0, 10], [0, 0]], [[1, 1], [3, 3], [5, 5], [1, 1]]], [[[0, 0], [10, 0], [10, 10], [0, 10], [0, 0]], [[1, 1], [3, 3], [5, 5], [1, 1]]]), ('boundary #18', [[[0, 0], [4, 0], [4, 4], [0, 4]]], None), ('boundary #20', [[[0, 0], [4, 0], [0, 0]]], None)]]
for label, args, expected in fixtures[N-1]:
    check(label, solve(args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
Boundary fixtureActualExpectedOutcome
control #0[[[63, -23], [56, 38], [-88, -26], [-62, -56], [-53, -42], [70, -48], [55, -40], [63, -23]], [[-10, -10], [-10, -4], [-6, -4], [-6, -10], [-10, -10]], [[-4, -10], [-4, -4], [0, -4], [0, -10], [-4, -10]], [[2, -10], [2, -4], [6, -4], [6, -10], [2, -10]]][[[63, -23], [56, 38], [-88, -26], [-62, -56], [-53, -42], [70, -48], [55, -40], [63, -23]], [[-10, -10], [-10, -4], [-6, -4], [-6, -10], [-10, -10]], [[-4, -10], [-4, -4], [0, -4], [0, -10], [-4, -10]], [[2, -10], [2, -4], [6, -4], [6, -10], [2, -10]]]Passed
control #1[[[53, -16], [42, 44], [-19, 64], [50, -21], [53, -16]], [[-10, -10], [-10, -4], [-6, -4], [-6, -10], [-10, -10]], [[-4, -10], [-4, -4], [0, -4], [0, -10], [-4, -10]]][[[53, -16], [42, 44], [-19, 64], [50, -21], [53, -16]], [[-10, -10], [-10, -4], [-6, -4], [-6, -10], [-10, -10]], [[-4, -10], [-4, -4], [0, -4], [0, -10], [-4, -10]]]Passed
control #2[[[57, -46], [-12, 64], [-55, 32], [24, -78], [57, -46]], [[-10, -10], [-10, -4], [-6, -4], [-6, -10], [-10, -10]], [[-4, -10], [-4, -4], [0, -4], [0, -10], [-4, -10]], [[2, -10], [2, -4], [6, -4], [6, -10], [2, -10]]][[[57, -46], [-12, 64], [-55, 32], [24, -78], [57, -46]], [[-10, -10], [-10, -4], [-6, -4], [-6, -10], [-10, -10]], [[-4, -10], [-4, -4], [0, -4], [0, -10], [-4, -10]], [[2, -10], [2, -4], [6, -4], [6, -10], [2, -10]]]Passed
control #3[[[-15, -68], [50, 23], [53, 44], [-8, 57], [-14, 65], [-18, -70], [-15, -80], [-15, -68]]][[[-15, -68], [50, 23], [53, 44], [-8, 57], [-14, 65], [-18, -70], [-15, -80], [-15, -68]]]Passed
control #4[[[69, 12], [-70, 38], [-68, -6], [-66, -30], [11, -70], [34, -72], [36, -68], [63, -28], [69, 12]], [[-10, -10], [-10, -4], [-6, -4], [-6, -10], [-10, -10]]][[[69, 12], [-70, 38], [-68, -6], [-66, -30], [11, -70], [34, -72], [36, -68], [63, -28], [69, 12]], [[-10, -10], [-10, -4], [-6, -4], [-6, -10], [-10, -10]]]Passed
control #5[[[12, -61], [-33, 50], [-56, 51], [-57, 29], [-50, 26], [12, -61]], [[-10, -10], [-10, -4], [-6, -4], [-6, -10], [-10, -10]]][[[12, -61], [-33, 50], [-56, 51], [-57, 29], [-50, 26], [12, -61]], [[-10, -10], [-10, -4], [-6, -4], [-6, -10], [-10, -10]]]Passed
boundary #16[[[0, 0], [5, 0], [10, 0], [0, 0]]][[[0, 0], [5, 0], [10, 0], [0, 0]]]Passed
boundary #20NoneNonePassed

SHA-256 / 966f06055c7fdedbf7fe56416343eab31b9f5350ebf22d3e7bb4f4754b3177f8

Verification & scope

Stipulated deterministic toy contract on a bounded input domain; results are rounded as stated and no conformance with any published standard or library is claimed. This reproducer isolates one failure mechanism. Results cover the supplied fixtures. Variants within a family share a test contract and should remain grouped when constructing evaluation splits. Related mechanisms with a shared evaluation_group must also remain together; these controlled models are not independent production incidents.

Observations recorded using Python 3.12.14 at 2026-09-29T14:48:20.046570+00:00.

Case digest / 1d9f80699b46ef5d6e76bd4b5c5aab0165cec03c239dc32fb537ed0948066473