FAILURE MAP
← Case archive

FA-70341 / GIS polygon topology / Open access

Right-hand rule ring orientation enforcement: hole orientation target · case 01

Holes are emitted with the same winding as the exterior, so renderers fill them.

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

ROOT CAUSE

Every ring, including holes, is forced counter-clockwise.

VERIFIED REPAIR

At the hole orientation target step restore `want_ccw = i == 0`, leaving the rest of the model unchanged.

Unsuccessful approach: Alternating the target by ring index makes the second hole counter-clockwise again.

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 = True
        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 #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 #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 #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]]]), ('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 #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 #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 #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 #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 #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]]]), ('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)], [('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 #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]]]), ('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], [-6, -10], [-6, -4], [-10, -4], [-10, -10]], [[-4, -10], [0, -10], [0, -4], [-4, -4], [-4, -10]], [[2, -10], [6, -10], [6, -4], [2, -4], [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[[[53, -16], [42, 44], [-19, 64], [50, -21], [53, -16]], [[-10, -10], [-6, -10], [-6, -4], [-10, -4], [-10, -10]], [[-4, -10], [0, -10], [0, -4], [-4, -4], [-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[[[57, -46], [-12, 64], [-55, 32], [24, -78], [57, -46]], [[-10, -10], [-6, -10], [-6, -4], [-10, -4], [-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]]]Failed
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], [-6, -10], [-6, -4], [-10, -4], [-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]]]Failed
control #5[[[12, -61], [-33, 50], [-56, 51], [-57, 29], [-50, 26], [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]]]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 #10[[[96, -2], [87, 6], [-81, -5], [-90, -24], [-77, -40], [-57, -50], [-33, -60], [-10, -53], [96, -2]]][[[96, -2], [87, 6], [-81, -5], [-90, -24], [-77, -40], [-57, -50], [-33, -60], [-10, -53], [96, -2]]]Passed

SHA-256 / 96c4f67244c2488c6962ec3699c5a64dc3e90d80cc47cfd22487ac4ea7383909

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 % 2 == 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 #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 #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 #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]]]), ('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 #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 #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 #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 #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 #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]]]), ('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)], [('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 #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]]]), ('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], [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]]]Failed
control #1[[[53, -16], [42, 44], [-19, 64], [50, -21], [53, -16]], [[-10, -10], [-10, -4], [-6, -4], [-6, -10], [-10, -10]], [[-4, -10], [0, -10], [0, -4], [-4, -4], [-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[[[57, -46], [-12, 64], [-55, 32], [24, -78], [57, -46]], [[-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]]][[[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[[[-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 #10[[[96, -2], [87, 6], [-81, -5], [-90, -24], [-77, -40], [-57, -50], [-33, -60], [-10, -53], [96, -2]]][[[96, -2], [87, 6], [-81, -5], [-90, -24], [-77, -40], [-57, -50], [-33, -60], [-10, -53], [96, -2]]]Passed

SHA-256 / 7312321b2715f20cc93850aaf63f567083881cc538037a380b59f17c83c14a28

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 #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 #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 #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]]]), ('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 #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 #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 #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 #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 #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]]]), ('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)], [('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 #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]]]), ('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 #10[[[96, -2], [87, 6], [-81, -5], [-90, -24], [-77, -40], [-57, -50], [-33, -60], [-10, -53], [96, -2]]][[[96, -2], [87, 6], [-81, -5], [-90, -24], [-77, -40], [-57, -50], [-33, -60], [-10, -53], [96, -2]]]Passed

SHA-256 / 6611e73181bc017aef0081af36524061075a4af228b6a2ffdf57825992193949

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

Case digest / dc49898d38ac6c6ac996eda5d9a895caa5c1d4a19c588581cc54f3fb970364ae