FAILURE MAP
← Case archive

FA-70716 / GIS polygon topology / Open access

WKT polygon and multipolygon ring structure: keyword case folding · case 01

Lower-case WKT from some databases is rejected.

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

ROOT CAUSE

Keywords are compared case-sensitively.

VERIFIED REPAIR

At the keyword case folding step restore `words = up.replace('(', ' ( ').split()`, leaving the rest of the model unchanged.

Unsuccessful approach: Only the geometry keyword is upper-cased; a lower-case EMPTY marker is still not recognised.

Case contract

Input: a WKT string. The keyword (case-insensitive) must be POLYGON or MULTIPOLYGON, else None; "<keyword> EMPTY" returns []. Otherwise parse the parenthesised body into polygons -> rings -> positions, keeping only x and y of every position (Z/M ordinates are dropped). Every ring must have at least 4 positions and be closed in x/y, else None. Return a list of polygons (a POLYGON gives a one-element list).

Why this case matters

WKT is the lingua franca between databases and GIS tools; losing a dimension or nesting level corrupts rings.

1 / The failure

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(x):
    s = x.strip()
    up = s.upper()
    words = s.replace('(', ' ( ').split()
    if not words or words[0] not in ('POLYGON', 'MULTIPOLYGON'):
        return None
    if len(words) == 2 and words[1] == 'EMPTY':
        return []
    if '(' not in s:
        return None
    body = s[s.index('('):]
    stack = [[]]
    cur = ''
    for ch in body:
        if ch == '(':
            stack.append([])
        elif ch in '),':
            if cur.strip():
                nums = [float(t) for t in cur.split()]
                stack[-1].append(nums[:2])
            cur = ''
            if ch == ')':
                done = stack.pop()
                stack[-1].append(done)
        else:
            cur += ch
    tree = stack[0][0]
    polys = [tree] if words[0] == 'POLYGON' else tree
    for poly in polys:
        for ring in poly:
            if len(ring) < 4 or ring[0] != ring[-1]:
                return None
    return polys
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('control #0', 'POLYGON ((0 0, 4 0, 4 4, 0 4, 0 0))', [[[[0.0, 0.0], [4.0, 0.0], [4.0, 4.0], [0.0, 4.0], [0.0, 0.0]]]]), ('control #1', 'POLYGON ((0 0, 10 0, 10 10, 0 10, 0 0), (2 2, 2 4, 4 4, 2 2))', [[[[0.0, 0.0], [10.0, 0.0], [10.0, 10.0], [0.0, 10.0], [0.0, 0.0]], [[2.0, 2.0], [2.0, 4.0], [4.0, 4.0], [2.0, 2.0]]]]), ('regression #2', 'POLYGON Z ((0 0 5, 4 0 5, 4 4 6, 0 0 5))', [[[[0.0, 0.0], [4.0, 0.0], [4.0, 4.0], [0.0, 0.0]]]]), ('regression #3', 'POLYGON ZM ((0 0 5 1, 4 0 5 2, 4 4 6 3, 0 0 5 1))', [[[[0.0, 0.0], [4.0, 0.0], [4.0, 4.0], [0.0, 0.0]]]]), ('regression #4', 'POLYGON M ((0 0 7, 4 0 8, 4 4 9, 0 0 7))', [[[[0.0, 0.0], [4.0, 0.0], [4.0, 4.0], [0.0, 0.0]]]]), ('boundary #5', 'POLYGON EMPTY', []), ('boundary #6', 'polygon empty', []), ('regression #7', 'MULTIPOLYGON (((0 0, 1 0, 1 1, 0 0)), ((5 5, 6 5, 6 6, 5 5), (5.2 5.1, 5.8 5.8, 5.8 5.1, 5.2 5.1)))', [[[[0.0, 0.0], [1.0, 0.0], [1.0, 1.0], [0.0, 0.0]]], [[[5.0, 5.0], [6.0, 5.0], [6.0, 6.0], [5.0, 5.0]], [[5.2, 5.1], [5.8, 5.8], [5.8, 5.1], [5.2, 5.1]]]])], [('regression #3', 'POLYGON ZM ((0 0 5 1, 4 0 5 2, 4 4 6 3, 0 0 5 1))', [[[[0.0, 0.0], [4.0, 0.0], [4.0, 4.0], [0.0, 0.0]]]]), ('regression #4', 'POLYGON M ((0 0 7, 4 0 8, 4 4 9, 0 0 7))', [[[[0.0, 0.0], [4.0, 0.0], [4.0, 4.0], [0.0, 0.0]]]]), ('boundary #5', 'POLYGON EMPTY', []), ('boundary #6', 'polygon empty', []), ('regression #7', 'MULTIPOLYGON (((0 0, 1 0, 1 1, 0 0)), ((5 5, 6 5, 6 6, 5 5), (5.2 5.1, 5.8 5.8, 5.8 5.1, 5.2 5.1)))', [[[[0.0, 0.0], [1.0, 0.0], [1.0, 1.0], [0.0, 0.0]]], [[[5.0, 5.0], [6.0, 5.0], [6.0, 6.0], [5.0, 5.0]], [[5.2, 5.1], [5.8, 5.8], [5.8, 5.1], [5.2, 5.1]]]]), ('regression #8', 'MULTIPOLYGON (((0 0, 1 0, 1 1, 0 0)))', [[[[0.0, 0.0], [1.0, 0.0], [1.0, 1.0], [0.0, 0.0]]]]), ('regression #9', 'multipolygon (((-1.5 -2, 3e2 0, 0 1e1, -1.5 -2)))', [[[[-1.5, -2.0], [300.0, 0.0], [0.0, 10.0], [-1.5, -2.0]]]]), ('boundary #10', 'POLYGON ((0 0, 4 0, 4 4, 0 1))', None)], [('boundary #6', 'polygon empty', []), ('regression #7', 'MULTIPOLYGON (((0 0, 1 0, 1 1, 0 0)), ((5 5, 6 5, 6 6, 5 5), (5.2 5.1, 5.8 5.8, 5.8 5.1, 5.2 5.1)))', [[[[0.0, 0.0], [1.0, 0.0], [1.0, 1.0], [0.0, 0.0]]], [[[5.0, 5.0], [6.0, 5.0], [6.0, 6.0], [5.0, 5.0]], [[5.2, 5.1], [5.8, 5.8], [5.8, 5.1], [5.2, 5.1]]]]), ('regression #8', 'MULTIPOLYGON (((0 0, 1 0, 1 1, 0 0)))', [[[[0.0, 0.0], [1.0, 0.0], [1.0, 1.0], [0.0, 0.0]]]]), ('regression #9', 'multipolygon (((-1.5 -2, 3e2 0, 0 1e1, -1.5 -2)))', [[[[-1.5, -2.0], [300.0, 0.0], [0.0, 10.0], [-1.5, -2.0]]]]), ('boundary #10', 'POLYGON ((0 0, 4 0, 4 4, 0 1))', None), ('boundary #11', 'POLYGON ((0 0, 4 0, 0 0))', None), ('control #12', 'Polygon((1 1,5 1,5 5,1 1))', [[[[1.0, 1.0], [5.0, 1.0], [5.0, 5.0], [1.0, 1.0]]]]), ('boundary #13', 'LINESTRING (0 0, 1 1)', None)], [('boundary #6', 'polygon empty', []), ('boundary #10', 'POLYGON ((0 0, 4 0, 4 4, 0 1))', None), ('boundary #11', 'POLYGON ((0 0, 4 0, 0 0))', None), ('control #12', 'Polygon((1 1,5 1,5 5,1 1))', [[[[1.0, 1.0], [5.0, 1.0], [5.0, 5.0], [1.0, 1.0]]]]), ('boundary #13', 'LINESTRING (0 0, 1 1)', None), ('boundary #14', 'MULTIPOLYGON EMPTY', []), ('control #15', '  POLYGON ((0 0, -3 0, -3 -3, 0 0))  ', [[[[0.0, 0.0], [-3.0, 0.0], [-3.0, -3.0], [0.0, 0.0]]]]), ('regression #16', 'MULTIPOLYGON Z (((0 0 1, 2 0 1, 2 2 1, 0 0 1)), ((9 9 0, 8 9 0, 8 8 0, 9 9 0)))', [[[[0.0, 0.0], [2.0, 0.0], [2.0, 2.0], [0.0, 0.0]]], [[[9.0, 9.0], [8.0, 9.0], [8.0, 8.0], [9.0, 9.0]]]])], [('control #0', 'POLYGON ((0 0, 4 0, 4 4, 0 4, 0 0))', [[[[0.0, 0.0], [4.0, 0.0], [4.0, 4.0], [0.0, 4.0], [0.0, 0.0]]]]), ('control #1', 'POLYGON ((0 0, 10 0, 10 10, 0 10, 0 0), (2 2, 2 4, 4 4, 2 2))', [[[[0.0, 0.0], [10.0, 0.0], [10.0, 10.0], [0.0, 10.0], [0.0, 0.0]], [[2.0, 2.0], [2.0, 4.0], [4.0, 4.0], [2.0, 2.0]]]]), ('boundary #6', 'polygon empty', []), ('regression #9', 'multipolygon (((-1.5 -2, 3e2 0, 0 1e1, -1.5 -2)))', [[[[-1.5, -2.0], [300.0, 0.0], [0.0, 10.0], [-1.5, -2.0]]]]), ('boundary #14', 'MULTIPOLYGON EMPTY', []), ('control #15', '  POLYGON ((0 0, -3 0, -3 -3, 0 0))  ', [[[[0.0, 0.0], [-3.0, 0.0], [-3.0, -3.0], [0.0, 0.0]]]]), ('regression #16', 'MULTIPOLYGON Z (((0 0 1, 2 0 1, 2 2 1, 0 0 1)), ((9 9 0, 8 9 0, 8 8 0, 9 9 0)))', [[[[0.0, 0.0], [2.0, 0.0], [2.0, 2.0], [0.0, 0.0]]], [[[9.0, 9.0], [8.0, 9.0], [8.0, 8.0], [9.0, 9.0]]]]), ('boundary #17', 'POLYGON ((0 0 1, 4 0 1, 4 4 1, 0 0 2))', [[[[0.0, 0.0], [4.0, 0.0], [4.0, 4.0], [0.0, 0.0]]]])]]
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[[[[0.0, 0.0], [4.0, 0.0], [4.0, 4.0], [0.0, 4.0], [0.0, 0.0]]]][[[[0.0, 0.0], [4.0, 0.0], [4.0, 4.0], [0.0, 4.0], [0.0, 0.0]]]]Passed
control #1[[[[0.0, 0.0], [10.0, 0.0], [10.0, 10.0], [0.0, 10.0], [0.0, 0.0]], [[2.0, 2.0], [2.0, 4.0], [4.0, 4.0], [2.0, 2.0]]]][[[[0.0, 0.0], [10.0, 0.0], [10.0, 10.0], [0.0, 10.0], [0.0, 0.0]], [[2.0, 2.0], [2.0, 4.0], [4.0, 4.0], [2.0, 2.0]]]]Passed
regression #2[[[[0.0, 0.0], [4.0, 0.0], [4.0, 4.0], [0.0, 0.0]]]][[[[0.0, 0.0], [4.0, 0.0], [4.0, 4.0], [0.0, 0.0]]]]Passed
regression #3[[[[0.0, 0.0], [4.0, 0.0], [4.0, 4.0], [0.0, 0.0]]]][[[[0.0, 0.0], [4.0, 0.0], [4.0, 4.0], [0.0, 0.0]]]]Passed
regression #4[[[[0.0, 0.0], [4.0, 0.0], [4.0, 4.0], [0.0, 0.0]]]][[[[0.0, 0.0], [4.0, 0.0], [4.0, 4.0], [0.0, 0.0]]]]Passed
boundary #5[][]Passed
boundary #6None[]Failed
regression #7[[[[0.0, 0.0], [1.0, 0.0], [1.0, 1.0], [0.0, 0.0]]], [[[5.0, 5.0], [6.0, 5.0], [6.0, 6.0], [5.0, 5.0]], [[5.2, 5.1], [5.8, 5.8], [5.8, 5.1], [5.2, 5.1]]]][[[[0.0, 0.0], [1.0, 0.0], [1.0, 1.0], [0.0, 0.0]]], [[[5.0, 5.0], [6.0, 5.0], [6.0, 6.0], [5.0, 5.0]], [[5.2, 5.1], [5.8, 5.8], [5.8, 5.1], [5.2, 5.1]]]]Passed

SHA-256 / 4fbf1f0fd1494d072021f3557fa8245e0246aa47d6ae3932d7f9c90a5dea14ed

2 / The unsuccessful fix

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(x):
    s = x.strip()
    up = s.upper()
    words = s.replace('(', ' ( ').split()
    words[:1] = [w.upper() for w in words[:1]]
    if not words or words[0] not in ('POLYGON', 'MULTIPOLYGON'):
        return None
    if len(words) == 2 and words[1] == 'EMPTY':
        return []
    if '(' not in s:
        return None
    body = s[s.index('('):]
    stack = [[]]
    cur = ''
    for ch in body:
        if ch == '(':
            stack.append([])
        elif ch in '),':
            if cur.strip():
                nums = [float(t) for t in cur.split()]
                stack[-1].append(nums[:2])
            cur = ''
            if ch == ')':
                done = stack.pop()
                stack[-1].append(done)
        else:
            cur += ch
    tree = stack[0][0]
    polys = [tree] if words[0] == 'POLYGON' else tree
    for poly in polys:
        for ring in poly:
            if len(ring) < 4 or ring[0] != ring[-1]:
                return None
    return polys
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('control #0', 'POLYGON ((0 0, 4 0, 4 4, 0 4, 0 0))', [[[[0.0, 0.0], [4.0, 0.0], [4.0, 4.0], [0.0, 4.0], [0.0, 0.0]]]]), ('control #1', 'POLYGON ((0 0, 10 0, 10 10, 0 10, 0 0), (2 2, 2 4, 4 4, 2 2))', [[[[0.0, 0.0], [10.0, 0.0], [10.0, 10.0], [0.0, 10.0], [0.0, 0.0]], [[2.0, 2.0], [2.0, 4.0], [4.0, 4.0], [2.0, 2.0]]]]), ('regression #2', 'POLYGON Z ((0 0 5, 4 0 5, 4 4 6, 0 0 5))', [[[[0.0, 0.0], [4.0, 0.0], [4.0, 4.0], [0.0, 0.0]]]]), ('regression #3', 'POLYGON ZM ((0 0 5 1, 4 0 5 2, 4 4 6 3, 0 0 5 1))', [[[[0.0, 0.0], [4.0, 0.0], [4.0, 4.0], [0.0, 0.0]]]]), ('regression #4', 'POLYGON M ((0 0 7, 4 0 8, 4 4 9, 0 0 7))', [[[[0.0, 0.0], [4.0, 0.0], [4.0, 4.0], [0.0, 0.0]]]]), ('boundary #5', 'POLYGON EMPTY', []), ('boundary #6', 'polygon empty', []), ('regression #7', 'MULTIPOLYGON (((0 0, 1 0, 1 1, 0 0)), ((5 5, 6 5, 6 6, 5 5), (5.2 5.1, 5.8 5.8, 5.8 5.1, 5.2 5.1)))', [[[[0.0, 0.0], [1.0, 0.0], [1.0, 1.0], [0.0, 0.0]]], [[[5.0, 5.0], [6.0, 5.0], [6.0, 6.0], [5.0, 5.0]], [[5.2, 5.1], [5.8, 5.8], [5.8, 5.1], [5.2, 5.1]]]])], [('regression #3', 'POLYGON ZM ((0 0 5 1, 4 0 5 2, 4 4 6 3, 0 0 5 1))', [[[[0.0, 0.0], [4.0, 0.0], [4.0, 4.0], [0.0, 0.0]]]]), ('regression #4', 'POLYGON M ((0 0 7, 4 0 8, 4 4 9, 0 0 7))', [[[[0.0, 0.0], [4.0, 0.0], [4.0, 4.0], [0.0, 0.0]]]]), ('boundary #5', 'POLYGON EMPTY', []), ('boundary #6', 'polygon empty', []), ('regression #7', 'MULTIPOLYGON (((0 0, 1 0, 1 1, 0 0)), ((5 5, 6 5, 6 6, 5 5), (5.2 5.1, 5.8 5.8, 5.8 5.1, 5.2 5.1)))', [[[[0.0, 0.0], [1.0, 0.0], [1.0, 1.0], [0.0, 0.0]]], [[[5.0, 5.0], [6.0, 5.0], [6.0, 6.0], [5.0, 5.0]], [[5.2, 5.1], [5.8, 5.8], [5.8, 5.1], [5.2, 5.1]]]]), ('regression #8', 'MULTIPOLYGON (((0 0, 1 0, 1 1, 0 0)))', [[[[0.0, 0.0], [1.0, 0.0], [1.0, 1.0], [0.0, 0.0]]]]), ('regression #9', 'multipolygon (((-1.5 -2, 3e2 0, 0 1e1, -1.5 -2)))', [[[[-1.5, -2.0], [300.0, 0.0], [0.0, 10.0], [-1.5, -2.0]]]]), ('boundary #10', 'POLYGON ((0 0, 4 0, 4 4, 0 1))', None)], [('boundary #6', 'polygon empty', []), ('regression #7', 'MULTIPOLYGON (((0 0, 1 0, 1 1, 0 0)), ((5 5, 6 5, 6 6, 5 5), (5.2 5.1, 5.8 5.8, 5.8 5.1, 5.2 5.1)))', [[[[0.0, 0.0], [1.0, 0.0], [1.0, 1.0], [0.0, 0.0]]], [[[5.0, 5.0], [6.0, 5.0], [6.0, 6.0], [5.0, 5.0]], [[5.2, 5.1], [5.8, 5.8], [5.8, 5.1], [5.2, 5.1]]]]), ('regression #8', 'MULTIPOLYGON (((0 0, 1 0, 1 1, 0 0)))', [[[[0.0, 0.0], [1.0, 0.0], [1.0, 1.0], [0.0, 0.0]]]]), ('regression #9', 'multipolygon (((-1.5 -2, 3e2 0, 0 1e1, -1.5 -2)))', [[[[-1.5, -2.0], [300.0, 0.0], [0.0, 10.0], [-1.5, -2.0]]]]), ('boundary #10', 'POLYGON ((0 0, 4 0, 4 4, 0 1))', None), ('boundary #11', 'POLYGON ((0 0, 4 0, 0 0))', None), ('control #12', 'Polygon((1 1,5 1,5 5,1 1))', [[[[1.0, 1.0], [5.0, 1.0], [5.0, 5.0], [1.0, 1.0]]]]), ('boundary #13', 'LINESTRING (0 0, 1 1)', None)], [('boundary #6', 'polygon empty', []), ('boundary #10', 'POLYGON ((0 0, 4 0, 4 4, 0 1))', None), ('boundary #11', 'POLYGON ((0 0, 4 0, 0 0))', None), ('control #12', 'Polygon((1 1,5 1,5 5,1 1))', [[[[1.0, 1.0], [5.0, 1.0], [5.0, 5.0], [1.0, 1.0]]]]), ('boundary #13', 'LINESTRING (0 0, 1 1)', None), ('boundary #14', 'MULTIPOLYGON EMPTY', []), ('control #15', '  POLYGON ((0 0, -3 0, -3 -3, 0 0))  ', [[[[0.0, 0.0], [-3.0, 0.0], [-3.0, -3.0], [0.0, 0.0]]]]), ('regression #16', 'MULTIPOLYGON Z (((0 0 1, 2 0 1, 2 2 1, 0 0 1)), ((9 9 0, 8 9 0, 8 8 0, 9 9 0)))', [[[[0.0, 0.0], [2.0, 0.0], [2.0, 2.0], [0.0, 0.0]]], [[[9.0, 9.0], [8.0, 9.0], [8.0, 8.0], [9.0, 9.0]]]])], [('control #0', 'POLYGON ((0 0, 4 0, 4 4, 0 4, 0 0))', [[[[0.0, 0.0], [4.0, 0.0], [4.0, 4.0], [0.0, 4.0], [0.0, 0.0]]]]), ('control #1', 'POLYGON ((0 0, 10 0, 10 10, 0 10, 0 0), (2 2, 2 4, 4 4, 2 2))', [[[[0.0, 0.0], [10.0, 0.0], [10.0, 10.0], [0.0, 10.0], [0.0, 0.0]], [[2.0, 2.0], [2.0, 4.0], [4.0, 4.0], [2.0, 2.0]]]]), ('boundary #6', 'polygon empty', []), ('regression #9', 'multipolygon (((-1.5 -2, 3e2 0, 0 1e1, -1.5 -2)))', [[[[-1.5, -2.0], [300.0, 0.0], [0.0, 10.0], [-1.5, -2.0]]]]), ('boundary #14', 'MULTIPOLYGON EMPTY', []), ('control #15', '  POLYGON ((0 0, -3 0, -3 -3, 0 0))  ', [[[[0.0, 0.0], [-3.0, 0.0], [-3.0, -3.0], [0.0, 0.0]]]]), ('regression #16', 'MULTIPOLYGON Z (((0 0 1, 2 0 1, 2 2 1, 0 0 1)), ((9 9 0, 8 9 0, 8 8 0, 9 9 0)))', [[[[0.0, 0.0], [2.0, 0.0], [2.0, 2.0], [0.0, 0.0]]], [[[9.0, 9.0], [8.0, 9.0], [8.0, 8.0], [9.0, 9.0]]]]), ('boundary #17', 'POLYGON ((0 0 1, 4 0 1, 4 4 1, 0 0 2))', [[[[0.0, 0.0], [4.0, 0.0], [4.0, 4.0], [0.0, 0.0]]]])]]
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[[[[0.0, 0.0], [4.0, 0.0], [4.0, 4.0], [0.0, 4.0], [0.0, 0.0]]]][[[[0.0, 0.0], [4.0, 0.0], [4.0, 4.0], [0.0, 4.0], [0.0, 0.0]]]]Passed
control #1[[[[0.0, 0.0], [10.0, 0.0], [10.0, 10.0], [0.0, 10.0], [0.0, 0.0]], [[2.0, 2.0], [2.0, 4.0], [4.0, 4.0], [2.0, 2.0]]]][[[[0.0, 0.0], [10.0, 0.0], [10.0, 10.0], [0.0, 10.0], [0.0, 0.0]], [[2.0, 2.0], [2.0, 4.0], [4.0, 4.0], [2.0, 2.0]]]]Passed
regression #2[[[[0.0, 0.0], [4.0, 0.0], [4.0, 4.0], [0.0, 0.0]]]][[[[0.0, 0.0], [4.0, 0.0], [4.0, 4.0], [0.0, 0.0]]]]Passed
regression #3[[[[0.0, 0.0], [4.0, 0.0], [4.0, 4.0], [0.0, 0.0]]]][[[[0.0, 0.0], [4.0, 0.0], [4.0, 4.0], [0.0, 0.0]]]]Passed
regression #4[[[[0.0, 0.0], [4.0, 0.0], [4.0, 4.0], [0.0, 0.0]]]][[[[0.0, 0.0], [4.0, 0.0], [4.0, 4.0], [0.0, 0.0]]]]Passed
boundary #5[][]Passed
boundary #6None[]Failed
regression #7[[[[0.0, 0.0], [1.0, 0.0], [1.0, 1.0], [0.0, 0.0]]], [[[5.0, 5.0], [6.0, 5.0], [6.0, 6.0], [5.0, 5.0]], [[5.2, 5.1], [5.8, 5.8], [5.8, 5.1], [5.2, 5.1]]]][[[[0.0, 0.0], [1.0, 0.0], [1.0, 1.0], [0.0, 0.0]]], [[[5.0, 5.0], [6.0, 5.0], [6.0, 6.0], [5.0, 5.0]], [[5.2, 5.1], [5.8, 5.8], [5.8, 5.1], [5.2, 5.1]]]]Passed

SHA-256 / ae9eb68227865214ee9b7a4126a94b24c2f1ac1dd00afff29f734ec422cc3f47

3 / The verified repair

Exit 0
"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(x):
    s = x.strip()
    up = s.upper()
    words = up.replace('(', ' ( ').split()
    if not words or words[0] not in ('POLYGON', 'MULTIPOLYGON'):
        return None
    if len(words) == 2 and words[1] == 'EMPTY':
        return []
    if '(' not in s:
        return None
    body = s[s.index('('):]
    stack = [[]]
    cur = ''
    for ch in body:
        if ch == '(':
            stack.append([])
        elif ch in '),':
            if cur.strip():
                nums = [float(t) for t in cur.split()]
                stack[-1].append(nums[:2])
            cur = ''
            if ch == ')':
                done = stack.pop()
                stack[-1].append(done)
        else:
            cur += ch
    tree = stack[0][0]
    polys = [tree] if words[0] == 'POLYGON' else tree
    for poly in polys:
        for ring in poly:
            if len(ring) < 4 or ring[0] != ring[-1]:
                return None
    return polys
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('control #0', 'POLYGON ((0 0, 4 0, 4 4, 0 4, 0 0))', [[[[0.0, 0.0], [4.0, 0.0], [4.0, 4.0], [0.0, 4.0], [0.0, 0.0]]]]), ('control #1', 'POLYGON ((0 0, 10 0, 10 10, 0 10, 0 0), (2 2, 2 4, 4 4, 2 2))', [[[[0.0, 0.0], [10.0, 0.0], [10.0, 10.0], [0.0, 10.0], [0.0, 0.0]], [[2.0, 2.0], [2.0, 4.0], [4.0, 4.0], [2.0, 2.0]]]]), ('regression #2', 'POLYGON Z ((0 0 5, 4 0 5, 4 4 6, 0 0 5))', [[[[0.0, 0.0], [4.0, 0.0], [4.0, 4.0], [0.0, 0.0]]]]), ('regression #3', 'POLYGON ZM ((0 0 5 1, 4 0 5 2, 4 4 6 3, 0 0 5 1))', [[[[0.0, 0.0], [4.0, 0.0], [4.0, 4.0], [0.0, 0.0]]]]), ('regression #4', 'POLYGON M ((0 0 7, 4 0 8, 4 4 9, 0 0 7))', [[[[0.0, 0.0], [4.0, 0.0], [4.0, 4.0], [0.0, 0.0]]]]), ('boundary #5', 'POLYGON EMPTY', []), ('boundary #6', 'polygon empty', []), ('regression #7', 'MULTIPOLYGON (((0 0, 1 0, 1 1, 0 0)), ((5 5, 6 5, 6 6, 5 5), (5.2 5.1, 5.8 5.8, 5.8 5.1, 5.2 5.1)))', [[[[0.0, 0.0], [1.0, 0.0], [1.0, 1.0], [0.0, 0.0]]], [[[5.0, 5.0], [6.0, 5.0], [6.0, 6.0], [5.0, 5.0]], [[5.2, 5.1], [5.8, 5.8], [5.8, 5.1], [5.2, 5.1]]]])], [('regression #3', 'POLYGON ZM ((0 0 5 1, 4 0 5 2, 4 4 6 3, 0 0 5 1))', [[[[0.0, 0.0], [4.0, 0.0], [4.0, 4.0], [0.0, 0.0]]]]), ('regression #4', 'POLYGON M ((0 0 7, 4 0 8, 4 4 9, 0 0 7))', [[[[0.0, 0.0], [4.0, 0.0], [4.0, 4.0], [0.0, 0.0]]]]), ('boundary #5', 'POLYGON EMPTY', []), ('boundary #6', 'polygon empty', []), ('regression #7', 'MULTIPOLYGON (((0 0, 1 0, 1 1, 0 0)), ((5 5, 6 5, 6 6, 5 5), (5.2 5.1, 5.8 5.8, 5.8 5.1, 5.2 5.1)))', [[[[0.0, 0.0], [1.0, 0.0], [1.0, 1.0], [0.0, 0.0]]], [[[5.0, 5.0], [6.0, 5.0], [6.0, 6.0], [5.0, 5.0]], [[5.2, 5.1], [5.8, 5.8], [5.8, 5.1], [5.2, 5.1]]]]), ('regression #8', 'MULTIPOLYGON (((0 0, 1 0, 1 1, 0 0)))', [[[[0.0, 0.0], [1.0, 0.0], [1.0, 1.0], [0.0, 0.0]]]]), ('regression #9', 'multipolygon (((-1.5 -2, 3e2 0, 0 1e1, -1.5 -2)))', [[[[-1.5, -2.0], [300.0, 0.0], [0.0, 10.0], [-1.5, -2.0]]]]), ('boundary #10', 'POLYGON ((0 0, 4 0, 4 4, 0 1))', None)], [('boundary #6', 'polygon empty', []), ('regression #7', 'MULTIPOLYGON (((0 0, 1 0, 1 1, 0 0)), ((5 5, 6 5, 6 6, 5 5), (5.2 5.1, 5.8 5.8, 5.8 5.1, 5.2 5.1)))', [[[[0.0, 0.0], [1.0, 0.0], [1.0, 1.0], [0.0, 0.0]]], [[[5.0, 5.0], [6.0, 5.0], [6.0, 6.0], [5.0, 5.0]], [[5.2, 5.1], [5.8, 5.8], [5.8, 5.1], [5.2, 5.1]]]]), ('regression #8', 'MULTIPOLYGON (((0 0, 1 0, 1 1, 0 0)))', [[[[0.0, 0.0], [1.0, 0.0], [1.0, 1.0], [0.0, 0.0]]]]), ('regression #9', 'multipolygon (((-1.5 -2, 3e2 0, 0 1e1, -1.5 -2)))', [[[[-1.5, -2.0], [300.0, 0.0], [0.0, 10.0], [-1.5, -2.0]]]]), ('boundary #10', 'POLYGON ((0 0, 4 0, 4 4, 0 1))', None), ('boundary #11', 'POLYGON ((0 0, 4 0, 0 0))', None), ('control #12', 'Polygon((1 1,5 1,5 5,1 1))', [[[[1.0, 1.0], [5.0, 1.0], [5.0, 5.0], [1.0, 1.0]]]]), ('boundary #13', 'LINESTRING (0 0, 1 1)', None)], [('boundary #6', 'polygon empty', []), ('boundary #10', 'POLYGON ((0 0, 4 0, 4 4, 0 1))', None), ('boundary #11', 'POLYGON ((0 0, 4 0, 0 0))', None), ('control #12', 'Polygon((1 1,5 1,5 5,1 1))', [[[[1.0, 1.0], [5.0, 1.0], [5.0, 5.0], [1.0, 1.0]]]]), ('boundary #13', 'LINESTRING (0 0, 1 1)', None), ('boundary #14', 'MULTIPOLYGON EMPTY', []), ('control #15', '  POLYGON ((0 0, -3 0, -3 -3, 0 0))  ', [[[[0.0, 0.0], [-3.0, 0.0], [-3.0, -3.0], [0.0, 0.0]]]]), ('regression #16', 'MULTIPOLYGON Z (((0 0 1, 2 0 1, 2 2 1, 0 0 1)), ((9 9 0, 8 9 0, 8 8 0, 9 9 0)))', [[[[0.0, 0.0], [2.0, 0.0], [2.0, 2.0], [0.0, 0.0]]], [[[9.0, 9.0], [8.0, 9.0], [8.0, 8.0], [9.0, 9.0]]]])], [('control #0', 'POLYGON ((0 0, 4 0, 4 4, 0 4, 0 0))', [[[[0.0, 0.0], [4.0, 0.0], [4.0, 4.0], [0.0, 4.0], [0.0, 0.0]]]]), ('control #1', 'POLYGON ((0 0, 10 0, 10 10, 0 10, 0 0), (2 2, 2 4, 4 4, 2 2))', [[[[0.0, 0.0], [10.0, 0.0], [10.0, 10.0], [0.0, 10.0], [0.0, 0.0]], [[2.0, 2.0], [2.0, 4.0], [4.0, 4.0], [2.0, 2.0]]]]), ('boundary #6', 'polygon empty', []), ('regression #9', 'multipolygon (((-1.5 -2, 3e2 0, 0 1e1, -1.5 -2)))', [[[[-1.5, -2.0], [300.0, 0.0], [0.0, 10.0], [-1.5, -2.0]]]]), ('boundary #14', 'MULTIPOLYGON EMPTY', []), ('control #15', '  POLYGON ((0 0, -3 0, -3 -3, 0 0))  ', [[[[0.0, 0.0], [-3.0, 0.0], [-3.0, -3.0], [0.0, 0.0]]]]), ('regression #16', 'MULTIPOLYGON Z (((0 0 1, 2 0 1, 2 2 1, 0 0 1)), ((9 9 0, 8 9 0, 8 8 0, 9 9 0)))', [[[[0.0, 0.0], [2.0, 0.0], [2.0, 2.0], [0.0, 0.0]]], [[[9.0, 9.0], [8.0, 9.0], [8.0, 8.0], [9.0, 9.0]]]]), ('boundary #17', 'POLYGON ((0 0 1, 4 0 1, 4 4 1, 0 0 2))', [[[[0.0, 0.0], [4.0, 0.0], [4.0, 4.0], [0.0, 0.0]]]])]]
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[[[[0.0, 0.0], [4.0, 0.0], [4.0, 4.0], [0.0, 4.0], [0.0, 0.0]]]][[[[0.0, 0.0], [4.0, 0.0], [4.0, 4.0], [0.0, 4.0], [0.0, 0.0]]]]Passed
control #1[[[[0.0, 0.0], [10.0, 0.0], [10.0, 10.0], [0.0, 10.0], [0.0, 0.0]], [[2.0, 2.0], [2.0, 4.0], [4.0, 4.0], [2.0, 2.0]]]][[[[0.0, 0.0], [10.0, 0.0], [10.0, 10.0], [0.0, 10.0], [0.0, 0.0]], [[2.0, 2.0], [2.0, 4.0], [4.0, 4.0], [2.0, 2.0]]]]Passed
regression #2[[[[0.0, 0.0], [4.0, 0.0], [4.0, 4.0], [0.0, 0.0]]]][[[[0.0, 0.0], [4.0, 0.0], [4.0, 4.0], [0.0, 0.0]]]]Passed
regression #3[[[[0.0, 0.0], [4.0, 0.0], [4.0, 4.0], [0.0, 0.0]]]][[[[0.0, 0.0], [4.0, 0.0], [4.0, 4.0], [0.0, 0.0]]]]Passed
regression #4[[[[0.0, 0.0], [4.0, 0.0], [4.0, 4.0], [0.0, 0.0]]]][[[[0.0, 0.0], [4.0, 0.0], [4.0, 4.0], [0.0, 0.0]]]]Passed
boundary #5[][]Passed
boundary #6[][]Passed
regression #7[[[[0.0, 0.0], [1.0, 0.0], [1.0, 1.0], [0.0, 0.0]]], [[[5.0, 5.0], [6.0, 5.0], [6.0, 6.0], [5.0, 5.0]], [[5.2, 5.1], [5.8, 5.8], [5.8, 5.1], [5.2, 5.1]]]][[[[0.0, 0.0], [1.0, 0.0], [1.0, 1.0], [0.0, 0.0]]], [[[5.0, 5.0], [6.0, 5.0], [6.0, 6.0], [5.0, 5.0]], [[5.2, 5.1], [5.8, 5.8], [5.8, 5.1], [5.2, 5.1]]]]Passed

SHA-256 / ab178526a29e27f5ebc61439dd66c6903fc5eb9bde7abac5392cca56c2a0a09e

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

Case digest / 4dc392042d907804a8658f7a1583e1b5b2fc076b0d33f183682b822ead456cbe