FA-88616 / Mesh topology invariants / Open access
Fan triangulation drops the last triangle of each polygon · case 01
Quads become single triangles and polygons leave a hole.
ROOT CAUSE
The fan loop stops at n-3.
VERIFIED REPAIR
Loop i from 1 to n-2 inclusive.
Unsuccessful approach: Starting the loop at 0 adds a degenerate triangle with the anchor twice.
Case contract
Input: polygon faces. A face with fewer than 3 corners returns ["bad-face", face]. Triangulate each face as a fan [f0, fi, fi+1] for i=1..n-2 (orientation preserved, anchor first). Return [triangles, diagonals added (sum n-3), growth in distinct undirected edge count].
Why this case matters
Mesh processing pipelines (remeshing, export, simulation, printing) trust these topological counts and adjacency answers; a wrong invariant silently accepts broken meshes or rejects valid ones.
1 / The failure
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(x):
faces=x
tris=[]
diag=0
for f in faces:
n=len(f)
if n<3: return ['bad-face',f]
for i in range(1,n-2):
tris.append([f[0],f[i],f[i+1]])
diag+=n-3
E=set()
for f in faces:
n=len(f)
for i in range(n):
a,b=f[i],f[(i+1)%n]
E.add((min(a,b),max(a,b)))
E2=set()
for t in tris:
for i in range(3):
a,b=t[i],t[(i+1)%3]
E2.add((min(a,b),max(a,b)))
return [tris,diag,len(E2)-len(E)]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['quad grid', [[[0, 1, 4, 3], [1, 2, 5, 4]]], [[[0, 1, 4], [0, 4, 3], [1, 2, 5], [1, 5, 4]], 2, 2]], ['pentagon', [[[0, 1, 2, 3, 4]]], [[[0, 1, 2], [0, 2, 3], [0, 3, 4]], 2, 2]], ['triangles only', [[[0, 1, 2], [2, 1, 3]]], [[[0, 1, 2], [2, 1, 3]], 0, 0]], ['cube', [[[0, 3, 2, 1], [4, 5, 6, 7], [0, 1, 5, 4], [1, 2, 6, 5], [2, 3, 7, 6], [3, 0, 4, 7]]], [[[0, 3, 2], [0, 2, 1], [4, 5, 6], [4, 6, 7], [0, 1, 5], [0, 5, 4], [1, 2, 6], [1, 6, 5], [2, 3, 7], [2, 7, 6], [3, 0, 4], [3, 4, 7]], 6, 6]], ['two-corner face', [[[0, 1, 2, 3], [4, 5]]], ['bad-face', [4, 5]]], ['mixed', [[[0, 1, 2, 3], [3, 2, 4]]], [[[0, 1, 2], [0, 2, 3], [3, 2, 4]], 1, 1]], ['diagonal already an edge', [[[0, 1, 2, 3], [0, 2, 5]]], [[[0, 1, 2], [0, 2, 3], [0, 2, 5]], 1, 0]]], [['pentagon', [[[0, 1, 2, 3, 4]]], [[[0, 1, 2], [0, 2, 3], [0, 3, 4]], 2, 2]], ['two-corner face', [[[0, 1, 2, 3], [4, 5]]], ['bad-face', [4, 5]]], ['mixed', [[[0, 1, 2, 3], [3, 2, 4]]], [[[0, 1, 2], [0, 2, 3], [3, 2, 4]], 1, 1]], ['diagonal already an edge', [[[0, 1, 2, 3], [0, 2, 5]]], [[[0, 1, 2], [0, 2, 3], [0, 2, 5]], 1, 0]], ['hexagon', [[[5, 4, 3, 2, 1, 0]]], [[[5, 4, 3], [5, 3, 2], [5, 2, 1], [5, 1, 0]], 3, 3]], ['triangle with bad face later', [[[0, 1, 2], [2, 1]]], ['bad-face', [2, 1]]], ['quad torus', [[[0, 3, 4, 1], [1, 4, 5, 2], [2, 5, 3, 0], [3, 6, 7, 4], [4, 7, 8, 5], [5, 8, 6, 3], [6, 0, 1, 7], [7, 1, 2, 8], [8, 2, 0, 6]]], [[[0, 3, 4], [0, 4, 1], [1, 4, 5], [1, 5, 2], [2, 5, 3], [2, 3, 0], [3, 6, 7], [3, 7, 4], [4, 7, 8], [4, 8, 5], [5, 8, 6], [5, 6, 3], [6, 0, 1], [6, 1, 7], [7, 1, 2], [7, 2, 8], [8, 2, 0], [8, 0, 6]], 9, 9]]], [['quad grid', [[[0, 1, 4, 3], [1, 2, 5, 4]]], [[[0, 1, 4], [0, 4, 3], [1, 2, 5], [1, 5, 4]], 2, 2]], ['pentagon', [[[0, 1, 2, 3, 4]]], [[[0, 1, 2], [0, 2, 3], [0, 3, 4]], 2, 2]], ['triangles only', [[[0, 1, 2], [2, 1, 3]]], [[[0, 1, 2], [2, 1, 3]], 0, 0]], ['hexagon', [[[5, 4, 3, 2, 1, 0]]], [[[5, 4, 3], [5, 3, 2], [5, 2, 1], [5, 1, 0]], 3, 3]], ['triangle with bad face later', [[[0, 1, 2], [2, 1]]], ['bad-face', [2, 1]]], ['quad torus', [[[0, 3, 4, 1], [1, 4, 5, 2], [2, 5, 3, 0], [3, 6, 7, 4], [4, 7, 8, 5], [5, 8, 6, 3], [6, 0, 1, 7], [7, 1, 2, 8], [8, 2, 0, 6]]], [[[0, 3, 4], [0, 4, 1], [1, 4, 5], [1, 5, 2], [2, 5, 3], [2, 3, 0], [3, 6, 7], [3, 7, 4], [4, 7, 8], [4, 8, 5], [5, 8, 6], [5, 6, 3], [6, 0, 1], [6, 1, 7], [7, 1, 2], [7, 2, 8], [8, 2, 0], [8, 0, 6]], 9, 9]], ['single quad', [[[7, 3, 5, 1]]], [[[7, 3, 5], [7, 5, 1]], 1, 1]]], [['quad grid', [[[0, 1, 4, 3], [1, 2, 5, 4]]], [[[0, 1, 4], [0, 4, 3], [1, 2, 5], [1, 5, 4]], 2, 2]], ['pentagon', [[[0, 1, 2, 3, 4]]], [[[0, 1, 2], [0, 2, 3], [0, 3, 4]], 2, 2]], ['triangles only', [[[0, 1, 2], [2, 1, 3]]], [[[0, 1, 2], [2, 1, 3]], 0, 0]], ['cube', [[[0, 3, 2, 1], [4, 5, 6, 7], [0, 1, 5, 4], [1, 2, 6, 5], [2, 3, 7, 6], [3, 0, 4, 7]]], [[[0, 3, 2], [0, 2, 1], [4, 5, 6], [4, 6, 7], [0, 1, 5], [0, 5, 4], [1, 2, 6], [1, 6, 5], [2, 3, 7], [2, 7, 6], [3, 0, 4], [3, 4, 7]], 6, 6]], ['two-corner face', [[[0, 1, 2, 3], [4, 5]]], ['bad-face', [4, 5]]], ['mixed', [[[0, 1, 2, 3], [3, 2, 4]]], [[[0, 1, 2], [0, 2, 3], [3, 2, 4]], 1, 1]], ['single quad', [[[7, 3, 5, 1]]], [[[7, 3, 5], [7, 5, 1]], 1, 1]]], [['triangles only', [[[0, 1, 2], [2, 1, 3]]], [[[0, 1, 2], [2, 1, 3]], 0, 0]], ['cube', [[[0, 3, 2, 1], [4, 5, 6, 7], [0, 1, 5, 4], [1, 2, 6, 5], [2, 3, 7, 6], [3, 0, 4, 7]]], [[[0, 3, 2], [0, 2, 1], [4, 5, 6], [4, 6, 7], [0, 1, 5], [0, 5, 4], [1, 2, 6], [1, 6, 5], [2, 3, 7], [2, 7, 6], [3, 0, 4], [3, 4, 7]], 6, 6]], ['two-corner face', [[[0, 1, 2, 3], [4, 5]]], ['bad-face', [4, 5]]], ['mixed', [[[0, 1, 2, 3], [3, 2, 4]]], [[[0, 1, 2], [0, 2, 3], [3, 2, 4]], 1, 1]], ['diagonal already an edge', [[[0, 1, 2, 3], [0, 2, 5]]], [[[0, 1, 2], [0, 2, 3], [0, 2, 5]], 1, 0]], ['hexagon', [[[5, 4, 3, 2, 1, 0]]], [[[5, 4, 3], [5, 3, 2], [5, 2, 1], [5, 1, 0]], 3, 3]], ['triangle with bad face later', [[[0, 1, 2], [2, 1]]], ['bad-face', [2, 1]]]]]
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 |
|---|---|---|---|
| quad grid | [[[0, 1, 4], [1, 2, 5]], 2, -1] | [[[0, 1, 4], [0, 4, 3], [1, 2, 5], [1, 5, 4]], 2, 2] | Failed |
| pentagon | [[[0, 1, 2], [0, 2, 3]], 2, 0] | [[[0, 1, 2], [0, 2, 3], [0, 3, 4]], 2, 2] | Failed |
| triangles only | [[], 0, -5] | [[[0, 1, 2], [2, 1, 3]], 0, 0] | Failed |
| cube | [[[0, 3, 2], [4, 5, 6], [0, 1, 5], [1, 2, 6], [2, 3, 7], [3, 0, 4]], 6, 4] | [[[0, 3, 2], [0, 2, 1], [4, 5, 6], [4, 6, 7], [0, 1, 5], [0, 5, 4], [1, 2, 6], [1, 6, 5], [2, 3, 7], [2, 7, 6], [3, 0, 4], [3, 4, 7]], 6, 6] | Failed |
| two-corner face | ['bad-face', [4, 5]] | ['bad-face', [4, 5]] | Passed |
| mixed | [[[0, 1, 2]], 1, -3] | [[[0, 1, 2], [0, 2, 3], [3, 2, 4]], 1, 1] | Failed |
| diagonal already an edge | [[[0, 1, 2]], 1, -4] | [[[0, 1, 2], [0, 2, 3], [0, 2, 5]], 1, 0] | Failed |
SHA-256 / 91964593d3930bd34057106c8e944e9322926fb425caea42561d0d2ef982d9b4
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(x):
faces=x
tris=[]
diag=0
for f in faces:
n=len(f)
if n<3: return ['bad-face',f]
for i in range(n-2):
tris.append([f[0],f[i],f[i+1]])
diag+=n-3
E=set()
for f in faces:
n=len(f)
for i in range(n):
a,b=f[i],f[(i+1)%n]
E.add((min(a,b),max(a,b)))
E2=set()
for t in tris:
for i in range(3):
a,b=t[i],t[(i+1)%3]
E2.add((min(a,b),max(a,b)))
return [tris,diag,len(E2)-len(E)]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['quad grid', [[[0, 1, 4, 3], [1, 2, 5, 4]]], [[[0, 1, 4], [0, 4, 3], [1, 2, 5], [1, 5, 4]], 2, 2]], ['pentagon', [[[0, 1, 2, 3, 4]]], [[[0, 1, 2], [0, 2, 3], [0, 3, 4]], 2, 2]], ['triangles only', [[[0, 1, 2], [2, 1, 3]]], [[[0, 1, 2], [2, 1, 3]], 0, 0]], ['cube', [[[0, 3, 2, 1], [4, 5, 6, 7], [0, 1, 5, 4], [1, 2, 6, 5], [2, 3, 7, 6], [3, 0, 4, 7]]], [[[0, 3, 2], [0, 2, 1], [4, 5, 6], [4, 6, 7], [0, 1, 5], [0, 5, 4], [1, 2, 6], [1, 6, 5], [2, 3, 7], [2, 7, 6], [3, 0, 4], [3, 4, 7]], 6, 6]], ['two-corner face', [[[0, 1, 2, 3], [4, 5]]], ['bad-face', [4, 5]]], ['mixed', [[[0, 1, 2, 3], [3, 2, 4]]], [[[0, 1, 2], [0, 2, 3], [3, 2, 4]], 1, 1]], ['diagonal already an edge', [[[0, 1, 2, 3], [0, 2, 5]]], [[[0, 1, 2], [0, 2, 3], [0, 2, 5]], 1, 0]]], [['pentagon', [[[0, 1, 2, 3, 4]]], [[[0, 1, 2], [0, 2, 3], [0, 3, 4]], 2, 2]], ['two-corner face', [[[0, 1, 2, 3], [4, 5]]], ['bad-face', [4, 5]]], ['mixed', [[[0, 1, 2, 3], [3, 2, 4]]], [[[0, 1, 2], [0, 2, 3], [3, 2, 4]], 1, 1]], ['diagonal already an edge', [[[0, 1, 2, 3], [0, 2, 5]]], [[[0, 1, 2], [0, 2, 3], [0, 2, 5]], 1, 0]], ['hexagon', [[[5, 4, 3, 2, 1, 0]]], [[[5, 4, 3], [5, 3, 2], [5, 2, 1], [5, 1, 0]], 3, 3]], ['triangle with bad face later', [[[0, 1, 2], [2, 1]]], ['bad-face', [2, 1]]], ['quad torus', [[[0, 3, 4, 1], [1, 4, 5, 2], [2, 5, 3, 0], [3, 6, 7, 4], [4, 7, 8, 5], [5, 8, 6, 3], [6, 0, 1, 7], [7, 1, 2, 8], [8, 2, 0, 6]]], [[[0, 3, 4], [0, 4, 1], [1, 4, 5], [1, 5, 2], [2, 5, 3], [2, 3, 0], [3, 6, 7], [3, 7, 4], [4, 7, 8], [4, 8, 5], [5, 8, 6], [5, 6, 3], [6, 0, 1], [6, 1, 7], [7, 1, 2], [7, 2, 8], [8, 2, 0], [8, 0, 6]], 9, 9]]], [['quad grid', [[[0, 1, 4, 3], [1, 2, 5, 4]]], [[[0, 1, 4], [0, 4, 3], [1, 2, 5], [1, 5, 4]], 2, 2]], ['pentagon', [[[0, 1, 2, 3, 4]]], [[[0, 1, 2], [0, 2, 3], [0, 3, 4]], 2, 2]], ['triangles only', [[[0, 1, 2], [2, 1, 3]]], [[[0, 1, 2], [2, 1, 3]], 0, 0]], ['hexagon', [[[5, 4, 3, 2, 1, 0]]], [[[5, 4, 3], [5, 3, 2], [5, 2, 1], [5, 1, 0]], 3, 3]], ['triangle with bad face later', [[[0, 1, 2], [2, 1]]], ['bad-face', [2, 1]]], ['quad torus', [[[0, 3, 4, 1], [1, 4, 5, 2], [2, 5, 3, 0], [3, 6, 7, 4], [4, 7, 8, 5], [5, 8, 6, 3], [6, 0, 1, 7], [7, 1, 2, 8], [8, 2, 0, 6]]], [[[0, 3, 4], [0, 4, 1], [1, 4, 5], [1, 5, 2], [2, 5, 3], [2, 3, 0], [3, 6, 7], [3, 7, 4], [4, 7, 8], [4, 8, 5], [5, 8, 6], [5, 6, 3], [6, 0, 1], [6, 1, 7], [7, 1, 2], [7, 2, 8], [8, 2, 0], [8, 0, 6]], 9, 9]], ['single quad', [[[7, 3, 5, 1]]], [[[7, 3, 5], [7, 5, 1]], 1, 1]]], [['quad grid', [[[0, 1, 4, 3], [1, 2, 5, 4]]], [[[0, 1, 4], [0, 4, 3], [1, 2, 5], [1, 5, 4]], 2, 2]], ['pentagon', [[[0, 1, 2, 3, 4]]], [[[0, 1, 2], [0, 2, 3], [0, 3, 4]], 2, 2]], ['triangles only', [[[0, 1, 2], [2, 1, 3]]], [[[0, 1, 2], [2, 1, 3]], 0, 0]], ['cube', [[[0, 3, 2, 1], [4, 5, 6, 7], [0, 1, 5, 4], [1, 2, 6, 5], [2, 3, 7, 6], [3, 0, 4, 7]]], [[[0, 3, 2], [0, 2, 1], [4, 5, 6], [4, 6, 7], [0, 1, 5], [0, 5, 4], [1, 2, 6], [1, 6, 5], [2, 3, 7], [2, 7, 6], [3, 0, 4], [3, 4, 7]], 6, 6]], ['two-corner face', [[[0, 1, 2, 3], [4, 5]]], ['bad-face', [4, 5]]], ['mixed', [[[0, 1, 2, 3], [3, 2, 4]]], [[[0, 1, 2], [0, 2, 3], [3, 2, 4]], 1, 1]], ['single quad', [[[7, 3, 5, 1]]], [[[7, 3, 5], [7, 5, 1]], 1, 1]]], [['triangles only', [[[0, 1, 2], [2, 1, 3]]], [[[0, 1, 2], [2, 1, 3]], 0, 0]], ['cube', [[[0, 3, 2, 1], [4, 5, 6, 7], [0, 1, 5, 4], [1, 2, 6, 5], [2, 3, 7, 6], [3, 0, 4, 7]]], [[[0, 3, 2], [0, 2, 1], [4, 5, 6], [4, 6, 7], [0, 1, 5], [0, 5, 4], [1, 2, 6], [1, 6, 5], [2, 3, 7], [2, 7, 6], [3, 0, 4], [3, 4, 7]], 6, 6]], ['two-corner face', [[[0, 1, 2, 3], [4, 5]]], ['bad-face', [4, 5]]], ['mixed', [[[0, 1, 2, 3], [3, 2, 4]]], [[[0, 1, 2], [0, 2, 3], [3, 2, 4]], 1, 1]], ['diagonal already an edge', [[[0, 1, 2, 3], [0, 2, 5]]], [[[0, 1, 2], [0, 2, 3], [0, 2, 5]], 1, 0]], ['hexagon', [[[5, 4, 3, 2, 1, 0]]], [[[5, 4, 3], [5, 3, 2], [5, 2, 1], [5, 1, 0]], 3, 3]], ['triangle with bad face later', [[[0, 1, 2], [2, 1]]], ['bad-face', [2, 1]]]]]
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 |
|---|---|---|---|
| quad grid | [[[0, 0, 1], [0, 1, 4], [1, 1, 2], [1, 2, 5]], 2, 1] | [[[0, 1, 4], [0, 4, 3], [1, 2, 5], [1, 5, 4]], 2, 2] | Failed |
| pentagon | [[[0, 0, 1], [0, 1, 2], [0, 2, 3]], 2, 1] | [[[0, 1, 2], [0, 2, 3], [0, 3, 4]], 2, 2] | Failed |
| triangles only | [[[0, 0, 1], [2, 2, 1]], 0, -1] | [[[0, 1, 2], [2, 1, 3]], 0, 0] | Failed |
| cube | [[[0, 0, 3], [0, 3, 2], [4, 4, 5], [4, 5, 6], [0, 0, 1], [0, 1, 5], [1, 1, 2], [1, 2, 6], [2, 2, 3], [2, 3, 7], [3, 3, 0], [3, 0, 4]], 6, 9] | [[[0, 3, 2], [0, 2, 1], [4, 5, 6], [4, 6, 7], [0, 1, 5], [0, 5, 4], [1, 2, 6], [1, 6, 5], [2, 3, 7], [2, 7, 6], [3, 0, 4], [3, 4, 7]], 6, 6] | Failed |
| two-corner face | ['bad-face', [4, 5]] | ['bad-face', [4, 5]] | Passed |
| mixed | [[[0, 0, 1], [0, 1, 2], [3, 3, 2]], 1, 0] | [[[0, 1, 2], [0, 2, 3], [3, 2, 4]], 1, 1] | Failed |
| diagonal already an edge | [[[0, 0, 1], [0, 1, 2], [0, 0, 2]], 1, -3] | [[[0, 1, 2], [0, 2, 3], [0, 2, 5]], 1, 0] | Failed |
SHA-256 / 905dff07f4e3f1636b85aa1c02251dd932662b0c84f25badb07bdd7f9b98c9f0
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(x):
faces=x
tris=[]
diag=0
for f in faces:
n=len(f)
if n<3: return ['bad-face',f]
for i in range(1,n-1):
tris.append([f[0],f[i],f[i+1]])
diag+=n-3
E=set()
for f in faces:
n=len(f)
for i in range(n):
a,b=f[i],f[(i+1)%n]
E.add((min(a,b),max(a,b)))
E2=set()
for t in tris:
for i in range(3):
a,b=t[i],t[(i+1)%3]
E2.add((min(a,b),max(a,b)))
return [tris,diag,len(E2)-len(E)]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['quad grid', [[[0, 1, 4, 3], [1, 2, 5, 4]]], [[[0, 1, 4], [0, 4, 3], [1, 2, 5], [1, 5, 4]], 2, 2]], ['pentagon', [[[0, 1, 2, 3, 4]]], [[[0, 1, 2], [0, 2, 3], [0, 3, 4]], 2, 2]], ['triangles only', [[[0, 1, 2], [2, 1, 3]]], [[[0, 1, 2], [2, 1, 3]], 0, 0]], ['cube', [[[0, 3, 2, 1], [4, 5, 6, 7], [0, 1, 5, 4], [1, 2, 6, 5], [2, 3, 7, 6], [3, 0, 4, 7]]], [[[0, 3, 2], [0, 2, 1], [4, 5, 6], [4, 6, 7], [0, 1, 5], [0, 5, 4], [1, 2, 6], [1, 6, 5], [2, 3, 7], [2, 7, 6], [3, 0, 4], [3, 4, 7]], 6, 6]], ['two-corner face', [[[0, 1, 2, 3], [4, 5]]], ['bad-face', [4, 5]]], ['mixed', [[[0, 1, 2, 3], [3, 2, 4]]], [[[0, 1, 2], [0, 2, 3], [3, 2, 4]], 1, 1]], ['diagonal already an edge', [[[0, 1, 2, 3], [0, 2, 5]]], [[[0, 1, 2], [0, 2, 3], [0, 2, 5]], 1, 0]]], [['pentagon', [[[0, 1, 2, 3, 4]]], [[[0, 1, 2], [0, 2, 3], [0, 3, 4]], 2, 2]], ['two-corner face', [[[0, 1, 2, 3], [4, 5]]], ['bad-face', [4, 5]]], ['mixed', [[[0, 1, 2, 3], [3, 2, 4]]], [[[0, 1, 2], [0, 2, 3], [3, 2, 4]], 1, 1]], ['diagonal already an edge', [[[0, 1, 2, 3], [0, 2, 5]]], [[[0, 1, 2], [0, 2, 3], [0, 2, 5]], 1, 0]], ['hexagon', [[[5, 4, 3, 2, 1, 0]]], [[[5, 4, 3], [5, 3, 2], [5, 2, 1], [5, 1, 0]], 3, 3]], ['triangle with bad face later', [[[0, 1, 2], [2, 1]]], ['bad-face', [2, 1]]], ['quad torus', [[[0, 3, 4, 1], [1, 4, 5, 2], [2, 5, 3, 0], [3, 6, 7, 4], [4, 7, 8, 5], [5, 8, 6, 3], [6, 0, 1, 7], [7, 1, 2, 8], [8, 2, 0, 6]]], [[[0, 3, 4], [0, 4, 1], [1, 4, 5], [1, 5, 2], [2, 5, 3], [2, 3, 0], [3, 6, 7], [3, 7, 4], [4, 7, 8], [4, 8, 5], [5, 8, 6], [5, 6, 3], [6, 0, 1], [6, 1, 7], [7, 1, 2], [7, 2, 8], [8, 2, 0], [8, 0, 6]], 9, 9]]], [['quad grid', [[[0, 1, 4, 3], [1, 2, 5, 4]]], [[[0, 1, 4], [0, 4, 3], [1, 2, 5], [1, 5, 4]], 2, 2]], ['pentagon', [[[0, 1, 2, 3, 4]]], [[[0, 1, 2], [0, 2, 3], [0, 3, 4]], 2, 2]], ['triangles only', [[[0, 1, 2], [2, 1, 3]]], [[[0, 1, 2], [2, 1, 3]], 0, 0]], ['hexagon', [[[5, 4, 3, 2, 1, 0]]], [[[5, 4, 3], [5, 3, 2], [5, 2, 1], [5, 1, 0]], 3, 3]], ['triangle with bad face later', [[[0, 1, 2], [2, 1]]], ['bad-face', [2, 1]]], ['quad torus', [[[0, 3, 4, 1], [1, 4, 5, 2], [2, 5, 3, 0], [3, 6, 7, 4], [4, 7, 8, 5], [5, 8, 6, 3], [6, 0, 1, 7], [7, 1, 2, 8], [8, 2, 0, 6]]], [[[0, 3, 4], [0, 4, 1], [1, 4, 5], [1, 5, 2], [2, 5, 3], [2, 3, 0], [3, 6, 7], [3, 7, 4], [4, 7, 8], [4, 8, 5], [5, 8, 6], [5, 6, 3], [6, 0, 1], [6, 1, 7], [7, 1, 2], [7, 2, 8], [8, 2, 0], [8, 0, 6]], 9, 9]], ['single quad', [[[7, 3, 5, 1]]], [[[7, 3, 5], [7, 5, 1]], 1, 1]]], [['quad grid', [[[0, 1, 4, 3], [1, 2, 5, 4]]], [[[0, 1, 4], [0, 4, 3], [1, 2, 5], [1, 5, 4]], 2, 2]], ['pentagon', [[[0, 1, 2, 3, 4]]], [[[0, 1, 2], [0, 2, 3], [0, 3, 4]], 2, 2]], ['triangles only', [[[0, 1, 2], [2, 1, 3]]], [[[0, 1, 2], [2, 1, 3]], 0, 0]], ['cube', [[[0, 3, 2, 1], [4, 5, 6, 7], [0, 1, 5, 4], [1, 2, 6, 5], [2, 3, 7, 6], [3, 0, 4, 7]]], [[[0, 3, 2], [0, 2, 1], [4, 5, 6], [4, 6, 7], [0, 1, 5], [0, 5, 4], [1, 2, 6], [1, 6, 5], [2, 3, 7], [2, 7, 6], [3, 0, 4], [3, 4, 7]], 6, 6]], ['two-corner face', [[[0, 1, 2, 3], [4, 5]]], ['bad-face', [4, 5]]], ['mixed', [[[0, 1, 2, 3], [3, 2, 4]]], [[[0, 1, 2], [0, 2, 3], [3, 2, 4]], 1, 1]], ['single quad', [[[7, 3, 5, 1]]], [[[7, 3, 5], [7, 5, 1]], 1, 1]]], [['triangles only', [[[0, 1, 2], [2, 1, 3]]], [[[0, 1, 2], [2, 1, 3]], 0, 0]], ['cube', [[[0, 3, 2, 1], [4, 5, 6, 7], [0, 1, 5, 4], [1, 2, 6, 5], [2, 3, 7, 6], [3, 0, 4, 7]]], [[[0, 3, 2], [0, 2, 1], [4, 5, 6], [4, 6, 7], [0, 1, 5], [0, 5, 4], [1, 2, 6], [1, 6, 5], [2, 3, 7], [2, 7, 6], [3, 0, 4], [3, 4, 7]], 6, 6]], ['two-corner face', [[[0, 1, 2, 3], [4, 5]]], ['bad-face', [4, 5]]], ['mixed', [[[0, 1, 2, 3], [3, 2, 4]]], [[[0, 1, 2], [0, 2, 3], [3, 2, 4]], 1, 1]], ['diagonal already an edge', [[[0, 1, 2, 3], [0, 2, 5]]], [[[0, 1, 2], [0, 2, 3], [0, 2, 5]], 1, 0]], ['hexagon', [[[5, 4, 3, 2, 1, 0]]], [[[5, 4, 3], [5, 3, 2], [5, 2, 1], [5, 1, 0]], 3, 3]], ['triangle with bad face later', [[[0, 1, 2], [2, 1]]], ['bad-face', [2, 1]]]]]
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 |
|---|---|---|---|
| quad grid | [[[0, 1, 4], [0, 4, 3], [1, 2, 5], [1, 5, 4]], 2, 2] | [[[0, 1, 4], [0, 4, 3], [1, 2, 5], [1, 5, 4]], 2, 2] | Passed |
| pentagon | [[[0, 1, 2], [0, 2, 3], [0, 3, 4]], 2, 2] | [[[0, 1, 2], [0, 2, 3], [0, 3, 4]], 2, 2] | Passed |
| triangles only | [[[0, 1, 2], [2, 1, 3]], 0, 0] | [[[0, 1, 2], [2, 1, 3]], 0, 0] | Passed |
| cube | [[[0, 3, 2], [0, 2, 1], [4, 5, 6], [4, 6, 7], [0, 1, 5], [0, 5, 4], [1, 2, 6], [1, 6, 5], [2, 3, 7], [2, 7, 6], [3, 0, 4], [3, 4, 7]], 6, 6] | [[[0, 3, 2], [0, 2, 1], [4, 5, 6], [4, 6, 7], [0, 1, 5], [0, 5, 4], [1, 2, 6], [1, 6, 5], [2, 3, 7], [2, 7, 6], [3, 0, 4], [3, 4, 7]], 6, 6] | Passed |
| two-corner face | ['bad-face', [4, 5]] | ['bad-face', [4, 5]] | Passed |
| mixed | [[[0, 1, 2], [0, 2, 3], [3, 2, 4]], 1, 1] | [[[0, 1, 2], [0, 2, 3], [3, 2, 4]], 1, 1] | Passed |
| diagonal already an edge | [[[0, 1, 2], [0, 2, 3], [0, 2, 5]], 1, 0] | [[[0, 1, 2], [0, 2, 3], [0, 2, 5]], 1, 0] | Passed |
SHA-256 / bffcae9ae3f7f5b9a553dc37fec779488121aea65a58173e7f1d726c80e5bd5d
Verification & scope
Pure combinatorial teaching model over integer face lists with a stipulated contract; no geometry kernel or file format is implied. 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:51:09.720006+00:00.
Case digest / 0a657e7b54fd389df21184335530770a8cac6e4b319912b2cc3dbbdcda42b145