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.
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 fixture | Actual | Expected | Outcome |
|---|---|---|---|
| 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 fixture | Actual | Expected | Outcome |
|---|---|---|---|
| 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 fixture | Actual | Expected | Outcome |
|---|---|---|---|
| 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