FAILURE MAP
← Case archive

FA-70351 / GIS polygon topology / Open access

Right-hand rule ring orientation enforcement: start-preserving reversal · case 01

Reoriented rings come out unclosed.

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

ROOT CAUSE

Reversal drops the closing position and never re-adds it.

VERIFIED REPAIR

At the start-preserving reversal step restore `ring = [ring[0]] + ring[-2:0:-1] + [ring[0]]`, leaving the rest of the model unchanged.

Unsuccessful approach: The reversed ring is re-closed but now starts at the old last vertex instead of the original start vertex.

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) < 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[:-1][::-1]
        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]]]), ('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 #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 #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 #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]]]), ('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]]]), ('boundary #16', [[[0, 0], [5, 0], [10, 0], [0, 0]]], [[[0, 0], [5, 0], [10, 0], [0, 0]]])], [('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 #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 #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]]]), ('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]]])], [('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 #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 #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 #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]]])], [('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 #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]]]), ('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 #19', [[[0, 0], [4, 0], [4, 4], [0, 4], [0, 1]]], 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[[[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, -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]]]Failed
control #1[[[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]]]Failed
control #2[[[-12, 64], [-55, 32], [24, -78], [57, -46]], [[-10, -10], [-10, -4], [-6, -4], [-6, -10], [-10, -10]], [[-4, -4], [0, -4], [0, -10], [-4, -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]]]Failed
control #3[[[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]]]Failed
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[[[-33, 50], [-56, 51], [-57, 29], [-50, 26], [12, -61]], [[-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]]]Failed
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]]]Passed
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]]]Passed

SHA-256 / 839198ba16cba25f724403eb2f558a601d37fb4366d5d4ce580d0566bcc6ee14

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[:-1][::-1] + [ring[-2]]
        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]]]), ('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 #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 #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 #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]]]), ('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]]]), ('boundary #16', [[[0, 0], [5, 0], [10, 0], [0, 0]]], [[[0, 0], [5, 0], [10, 0], [0, 0]]])], [('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 #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 #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]]]), ('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]]])], [('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 #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 #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 #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]]])], [('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 #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]]]), ('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 #19', [[[0, 0], [4, 0], [4, 4], [0, 4], [0, 1]]], 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[[[56, 38], [-88, -26], [-62, -56], [-53, -42], [70, -48], [55, -40], [63, -23], [56, 38]], [[-10, -10], [-10, -4], [-6, -4], [-6, -10], [-10, -10]], [[-4, -4], [0, -4], [0, -10], [-4, -10], [-4, -4]], [[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]]]Failed
control #1[[[42, 44], [-19, 64], [50, -21], [53, -16], [42, 44]], [[-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]]]Failed
control #2[[[-12, 64], [-55, 32], [24, -78], [57, -46], [-12, 64]], [[-10, -10], [-10, -4], [-6, -4], [-6, -10], [-10, -10]], [[-4, -4], [0, -4], [0, -10], [-4, -10], [-4, -4]], [[2, -4], [6, -4], [6, -10], [2, -10], [2, -4]]][[[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]]]Failed
control #3[[[50, 23], [53, 44], [-8, 57], [-14, 65], [-18, -70], [-15, -80], [-15, -68], [50, 23]]][[[-15, -68], [50, 23], [53, 44], [-8, 57], [-14, 65], [-18, -70], [-15, -80], [-15, -68]]]Failed
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[[[-33, 50], [-56, 51], [-57, 29], [-50, 26], [12, -61], [-33, 50]], [[-10, -4], [-6, -4], [-6, -10], [-10, -10], [-10, -4]]][[[12, -61], [-33, 50], [-56, 51], [-57, 29], [-50, 26], [12, -61]], [[-10, -10], [-10, -4], [-6, -4], [-6, -10], [-10, -10]]]Failed
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]]]Passed
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]]]Passed

SHA-256 / 256c90173bba6712c35ba4f3f5148db20fcff74120bd4f915d6bbbf08c4e7ea0

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]]]), ('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 #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 #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 #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]]]), ('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]]]), ('boundary #16', [[[0, 0], [5, 0], [10, 0], [0, 0]]], [[[0, 0], [5, 0], [10, 0], [0, 0]]])], [('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 #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 #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]]]), ('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]]])], [('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 #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 #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 #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]]])], [('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 #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]]]), ('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 #19', [[[0, 0], [4, 0], [4, 4], [0, 4], [0, 1]]], 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
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]]]Passed
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]]]Passed

SHA-256 / b36c88fc4f97fcf5cdca49c53a72296837f1fe46bcb41c8d4d4a3d48dce1b002

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:19.935174+00:00.

Case digest / 517b3f1c39a02331b98f7414fe3d95df02f6a6d4495e61512b92e887fdd43b1d