broken_source:
"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(x):
    faces,a,b=x
    adj={}
    opp=[]
    ecount={}
    for f in faces:
        for i in range(3):
            u,v=f[i],f[(i+1)%3]
            adj.setdefault(u,set()).add(v)
            adj.setdefault(v,set()).add(u)
            k=(min(u,v),max(u,v))
            ecount[k]=ecount.get(k,0)+1
        if a in f and b in f:
            opp.append([w for w in f if w!=a and w!=b][0])
    k=(min(a,b),max(a,b))
    if k not in ecount: return [False,'no-edge']
    bnd=set()
    for (u,v),c in ecount.items():
        if c==1: bnd.update((u,v))
    if a in bnd and b in bnd and ecount[k]!=1: return [False,'boundary']
    if (adj[a]&adj[b])!=set(opp): return [False,'link']
    if not bnd and len(adj)<=4: return [False,'minimal']
    return [True,'ok']
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['disk spoke', [[[[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 5], [0, 5, 1]], 0, 1]], [True, 'ok']], ['disk rim', [[[[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 5], [0, 5, 1]], 1, 2]], [True, 'ok']], ['fan interior edge', [[[[0, 1, 2], [0, 2, 3], [0, 3, 4]], 0, 2]], [False, 'boundary']], ['fan missing edge', [[[[0, 1, 2], [0, 2, 3], [0, 3, 4]], 1, 3]], [False, 'no-edge']], ['tetrahedron edge', [[[[0, 2, 1], [0, 1, 3], [1, 2, 3], [0, 3, 2]], 0, 1]], [False, 'minimal']], ['octahedron edge', [[[[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 1], [5, 2, 1], [5, 3, 2], [5, 4, 3], [5, 1, 4]], 0, 1]], [True, 'ok']], ['strip over-constrained', [[[[0, 1, 2], [0, 2, 3], [0, 3, 1], [1, 3, 4]], 1, 3]], [False, 'link']]], [['fan missing edge', [[[[0, 1, 2], [0, 2, 3], [0, 3, 4]], 1, 3]], [False, 'no-edge']], ['tetrahedron edge', [[[[0, 2, 1], [0, 1, 3], [1, 2, 3], [0, 3, 2]], 0, 1]], [False, 'minimal']], ['octahedron edge', [[[[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 1], [5, 2, 1], [5, 3, 2], [5, 4, 3], [5, 1, 4]], 0, 1]], [True, 'ok']], ['octahedron reversed', [[[[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 1], [5, 2, 1], [5, 3, 2], [5, 4, 3], [5, 1, 4]], 5, 2]], [True, 'ok']], ['open tetra cap', [[[[0, 1, 2], [0, 2, 3], [0, 3, 1]], 1, 2]], [False, 'link']], ['two triangles shared edge', [[[[0, 1, 2], [2, 1, 3]], 1, 2]], [False, 'boundary']], ['strip over-constrained', [[[[0, 1, 2], [0, 2, 3], [0, 3, 1], [1, 3, 4]], 1, 3]], [False, 'link']]], [['octahedron reversed', [[[[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 1], [5, 2, 1], [5, 3, 2], [5, 4, 3], [5, 1, 4]], 5, 2]], [True, 'ok']], ['open tetra cap', [[[[0, 1, 2], [0, 2, 3], [0, 3, 1]], 1, 2]], [False, 'link']], ['two triangles shared edge', [[[[0, 1, 2], [2, 1, 3]], 1, 2]], [False, 'boundary']], ['two triangles rim edge', [[[[0, 1, 2], [2, 1, 3]], 0, 1]], [True, 'ok']], ['torus edge', [[[[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]], 0, 1]], [False, 'link']], ['cylinder rung', [[[[0, 1, 5], [0, 5, 4], [1, 2, 6], [1, 6, 5], [2, 3, 7], [2, 7, 6], [3, 0, 4], [3, 4, 7]], 0, 5]], [False, 'boundary']], ['strip over-constrained', [[[[0, 1, 2], [0, 2, 3], [0, 3, 1], [1, 3, 4]], 1, 3]], [False, 'link']]], [['two triangles rim edge', [[[[0, 1, 2], [2, 1, 3]], 0, 1]], [True, 'ok']], ['torus edge', [[[[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]], 0, 1]], [False, 'link']], ['cylinder rung', [[[[0, 1, 5], [0, 5, 4], [1, 2, 6], [1, 6, 5], [2, 3, 7], [2, 7, 6], [3, 0, 4], [3, 4, 7]], 0, 5]], [False, 'boundary']], ['strip over-constrained', [[[[0, 1, 2], [0, 2, 3], [0, 3, 1], [1, 3, 4]], 1, 3]], [False, 'link']], ['grid diagonal', [[[[0, 1, 4], [0, 4, 3], [1, 2, 5], [1, 5, 4], [3, 4, 7], [3, 7, 6], [4, 5, 8], [4, 8, 7]], 0, 4]], [True, 'ok']], ['grid interior spoke', [[[[0, 1, 4], [0, 4, 3], [1, 2, 5], [1, 5, 4], [3, 4, 7], [3, 7, 6], [4, 5, 8], [4, 8, 7]], 4, 5]], [True, 'ok']], ['rotated face order', [[[[2, 0, 1], [3, 0, 2]], 0, 2]], [False, 'boundary']]], [['disk spoke', [[[[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 5], [0, 5, 1]], 0, 1]], [True, 'ok']], ['disk rim', [[[[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 5], [0, 5, 1]], 1, 2]], [True, 'ok']], ['fan interior edge', [[[[0, 1, 2], [0, 2, 3], [0, 3, 4]], 0, 2]], [False, 'boundary']], ['strip over-constrained', [[[[0, 1, 2], [0, 2, 3], [0, 3, 1], [1, 3, 4]], 1, 3]], [False, 'link']], ['grid diagonal', [[[[0, 1, 4], [0, 4, 3], [1, 2, 5], [1, 5, 4], [3, 4, 7], [3, 7, 6], [4, 5, 8], [4, 8, 7]], 0, 4]], [True, 'ok']], ['grid interior spoke', [[[[0, 1, 4], [0, 4, 3], [1, 2, 5], [1, 5, 4], [3, 4, 7], [3, 7, 6], [4, 5, 8], [4, 8, 7]], 4, 5]], [True, 'ok']], ['rotated face order', [[[[2, 0, 1], [3, 0, 2]], 0, 2]], [False, 'boundary']]]]
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)

source:
"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(x):
    faces,a,b=x
    adj={}
    opp=[]
    ecount={}
    for f in faces:
        for i in range(3):
            u,v=f[i],f[(i+1)%3]
            adj.setdefault(u,set()).add(v)
            adj.setdefault(v,set()).add(u)
            k=(min(u,v),max(u,v))
            ecount[k]=ecount.get(k,0)+1
        if a in f and b in f:
            opp.append([w for w in f if w!=a and w!=b][0])
    k=(min(a,b),max(a,b))
    if k not in ecount: return [False,'no-edge']
    bnd=set()
    for (u,v),c in ecount.items():
        if c==1: bnd.update((u,v))
    if a in bnd and b in bnd and ecount[k]!=1: return [False,'boundary']
    if not bnd and len(adj)<=4: return [False,'minimal']
    if (adj[a]&adj[b])!=set(opp): return [False,'link']
    return [True,'ok']
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['disk spoke', [[[[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 5], [0, 5, 1]], 0, 1]], [True, 'ok']], ['disk rim', [[[[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 5], [0, 5, 1]], 1, 2]], [True, 'ok']], ['fan interior edge', [[[[0, 1, 2], [0, 2, 3], [0, 3, 4]], 0, 2]], [False, 'boundary']], ['fan missing edge', [[[[0, 1, 2], [0, 2, 3], [0, 3, 4]], 1, 3]], [False, 'no-edge']], ['tetrahedron edge', [[[[0, 2, 1], [0, 1, 3], [1, 2, 3], [0, 3, 2]], 0, 1]], [False, 'minimal']], ['octahedron edge', [[[[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 1], [5, 2, 1], [5, 3, 2], [5, 4, 3], [5, 1, 4]], 0, 1]], [True, 'ok']], ['strip over-constrained', [[[[0, 1, 2], [0, 2, 3], [0, 3, 1], [1, 3, 4]], 1, 3]], [False, 'link']]], [['fan missing edge', [[[[0, 1, 2], [0, 2, 3], [0, 3, 4]], 1, 3]], [False, 'no-edge']], ['tetrahedron edge', [[[[0, 2, 1], [0, 1, 3], [1, 2, 3], [0, 3, 2]], 0, 1]], [False, 'minimal']], ['octahedron edge', [[[[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 1], [5, 2, 1], [5, 3, 2], [5, 4, 3], [5, 1, 4]], 0, 1]], [True, 'ok']], ['octahedron reversed', [[[[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 1], [5, 2, 1], [5, 3, 2], [5, 4, 3], [5, 1, 4]], 5, 2]], [True, 'ok']], ['open tetra cap', [[[[0, 1, 2], [0, 2, 3], [0, 3, 1]], 1, 2]], [False, 'link']], ['two triangles shared edge', [[[[0, 1, 2], [2, 1, 3]], 1, 2]], [False, 'boundary']], ['strip over-constrained', [[[[0, 1, 2], [0, 2, 3], [0, 3, 1], [1, 3, 4]], 1, 3]], [False, 'link']]], [['octahedron reversed', [[[[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 1], [5, 2, 1], [5, 3, 2], [5, 4, 3], [5, 1, 4]], 5, 2]], [True, 'ok']], ['open tetra cap', [[[[0, 1, 2], [0, 2, 3], [0, 3, 1]], 1, 2]], [False, 'link']], ['two triangles shared edge', [[[[0, 1, 2], [2, 1, 3]], 1, 2]], [False, 'boundary']], ['two triangles rim edge', [[[[0, 1, 2], [2, 1, 3]], 0, 1]], [True, 'ok']], ['torus edge', [[[[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]], 0, 1]], [False, 'link']], ['cylinder rung', [[[[0, 1, 5], [0, 5, 4], [1, 2, 6], [1, 6, 5], [2, 3, 7], [2, 7, 6], [3, 0, 4], [3, 4, 7]], 0, 5]], [False, 'boundary']], ['strip over-constrained', [[[[0, 1, 2], [0, 2, 3], [0, 3, 1], [1, 3, 4]], 1, 3]], [False, 'link']]], [['two triangles rim edge', [[[[0, 1, 2], [2, 1, 3]], 0, 1]], [True, 'ok']], ['torus edge', [[[[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]], 0, 1]], [False, 'link']], ['cylinder rung', [[[[0, 1, 5], [0, 5, 4], [1, 2, 6], [1, 6, 5], [2, 3, 7], [2, 7, 6], [3, 0, 4], [3, 4, 7]], 0, 5]], [False, 'boundary']], ['strip over-constrained', [[[[0, 1, 2], [0, 2, 3], [0, 3, 1], [1, 3, 4]], 1, 3]], [False, 'link']], ['grid diagonal', [[[[0, 1, 4], [0, 4, 3], [1, 2, 5], [1, 5, 4], [3, 4, 7], [3, 7, 6], [4, 5, 8], [4, 8, 7]], 0, 4]], [True, 'ok']], ['grid interior spoke', [[[[0, 1, 4], [0, 4, 3], [1, 2, 5], [1, 5, 4], [3, 4, 7], [3, 7, 6], [4, 5, 8], [4, 8, 7]], 4, 5]], [True, 'ok']], ['rotated face order', [[[[2, 0, 1], [3, 0, 2]], 0, 2]], [False, 'boundary']]], [['disk spoke', [[[[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 5], [0, 5, 1]], 0, 1]], [True, 'ok']], ['disk rim', [[[[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 5], [0, 5, 1]], 1, 2]], [True, 'ok']], ['fan interior edge', [[[[0, 1, 2], [0, 2, 3], [0, 3, 4]], 0, 2]], [False, 'boundary']], ['strip over-constrained', [[[[0, 1, 2], [0, 2, 3], [0, 3, 1], [1, 3, 4]], 1, 3]], [False, 'link']], ['grid diagonal', [[[[0, 1, 4], [0, 4, 3], [1, 2, 5], [1, 5, 4], [3, 4, 7], [3, 7, 6], [4, 5, 8], [4, 8, 7]], 0, 4]], [True, 'ok']], ['grid interior spoke', [[[[0, 1, 4], [0, 4, 3], [1, 2, 5], [1, 5, 4], [3, 4, 7], [3, 7, 6], [4, 5, 8], [4, 8, 7]], 4, 5]], [True, 'ok']], ['rotated face order', [[[[2, 0, 1], [3, 0, 2]], 0, 2]], [False, 'boundary']]]]
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)

prompt:
A collapse that violates both conditions is reported as "boundary" rather than "link".

Input [faces, a, b] for a triangle mesh. Collapsing edge (a,b) is checked in order: missing edge -> [false,"no-edge"]; common neighbours of a and b must equal the opposite vertices of the triangles on the edge -> else [false,"link"]; if a and b are both boundary vertices the edge itself must be a boundary edge -> else [false,"boundary"]; a closed mesh with 4 or fewer vertices -> [false,"minimal"]; otherwise [true,"ok"].

split: open-access


meaning: Fixture-count band, not measured model difficulty

deps: stdlib

prompt:
Predicted edge counts are low and the Euler characteristic drifts after subdivision.

Input [V,E,arities,B,scheme,levels]: counts of a mesh with face sizes "arities" and B boundary edges. Loop (triangles only, else "non-triangle"): V+=E, E=2E+3F, F=4F. Catmull-Clark: V=V+E+F, E=2E+sum(arities), faces become sum(arities) quads. Boundary edges double per level. Return [V,E,F,B,V-E+F] after the given levels.

split: open-access


prompt:
Vertex predictions are low for every mesh.

Input [V,E,arities,B,scheme,levels]: counts of a mesh with face sizes "arities" and B boundary edges. Loop (triangles only, else "non-triangle"): V+=E, E=2E+3F, F=4F. Catmull-Clark: V=V+E+F, E=2E+sum(arities), faces become sum(arities) quads. Boundary edges double per level. Return [V,E,F,B,V-E+F] after the given levels.

split: open-access


prompt:
Edge predictions are low for any mesh whose faces are not all triangles or quads.

Input [V,E,arities,B,scheme,levels]: counts of a mesh with face sizes "arities" and B boundary edges. Loop (triangles only, else "non-triangle"): V+=E, E=2E+3F, F=4F. Catmull-Clark: V=V+E+F, E=2E+sum(arities), faces become sum(arities) quads. Boundary edges double per level. Return [V,E,F,B,V-E+F] after the given levels.

split: open-access


prompt:
Face counts do not grow and later levels use stale arities.

Input [V,E,arities,B,scheme,levels]: counts of a mesh with face sizes "arities" and B boundary edges. Loop (triangles only, else "non-triangle"): V+=E, E=2E+3F, F=4F. Catmull-Clark: V=V+E+F, E=2E+sum(arities), faces become sum(arities) quads. Boundary edges double per level. Return [V,E,F,B,V-E+F] after the given levels.

split: open-access


prompt:
Open meshes report their original boundary edge count after subdivision.

Input [V,E,arities,B,scheme,levels]: counts of a mesh with face sizes "arities" and B boundary edges. Loop (triangles only, else "non-triangle"): V+=E, E=2E+3F, F=4F. Catmull-Clark: V=V+E+F, E=2E+sum(arities), faces become sum(arities) quads. Boundary edges double per level. Return [V,E,F,B,V-E+F] after the given levels.

split: open-access


prompt:
Quads are counted as if they were triangles.

Input [V,E,arities,B,scheme,levels]: counts of a mesh with face sizes "arities" and B boundary edges. Loop (triangles only, else "non-triangle"): V+=E, E=2E+3F, F=4F. Catmull-Clark: V=V+E+F, E=2E+sum(arities), faces become sum(arities) quads. Boundary edges double per level. Return [V,E,F,B,V-E+F] after the given levels.

split: open-access


broken_source:
"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(x):
    faces=x
    edge_faces={}
    for fi,f in enumerate(faces):
        n=len(f)
        for i in range(n):
            a,b=f[i],f[(i+1)%n]
            edge_faces.setdefault((min(a,b),max(a,b)),[]).append((fi,a,b))
    if any(len(v)>2 for v in edge_faces.values()): return 'non-manifold'
    flip=[None]*len(faces)
    for seed in range(len(faces)):
        if flip[seed] is not None: continue
        flip[seed]=0
        queue=[seed]
        while queue:
            fi=queue.pop(0)
            f=faces[fi]
            n=len(f)
            for i in range(n):
                a,b=f[i],f[(i+1)%n]
                for gj,c,d in edge_faces[(min(a,b),max(a,b))]:
                    if gj==fi: continue
                    same=1 if (c,d)==(b,a) else 0
                    want=flip[fi]^same
                    if flip[gj] is None:
                        flip[gj]=want
                        queue.append(gj)
                    elif flip[gj]!=want:
                        return [False,[]]
    return [True,[i for i in range(len(faces)) if flip[i]]]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['consistent tetrahedron', [[[0, 2, 1], [0, 1, 3], [1, 2, 3], [0, 3, 2]]], [True, []]], ['one flipped face', [[[0, 2, 1], [0, 3, 1], [1, 2, 3], [0, 3, 2]]], [True, [1]]], ['mobius', [[[0, 3, 4, 1], [1, 4, 5, 2], [2, 5, 0, 3]]], [False, []]], ['projective plane', [[[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 5], [0, 5, 1], [1, 2, 4], [2, 3, 5], [3, 4, 1], [4, 5, 2], [5, 1, 3]]], [False, []]], ['book', [[[0, 1, 2], [1, 0, 3], [0, 1, 4]]], 'non-manifold'], ['flipped pair', [[[0, 1, 2], [0, 1, 3]]], [True, [1]]], ['disk with two flips', [[[0, 1, 2], [0, 3, 2], [0, 3, 4], [0, 5, 4], [0, 5, 1]]], [True, [1, 3]]]], [['one flipped face', [[[0, 2, 1], [0, 3, 1], [1, 2, 3], [0, 3, 2]]], [True, [1]]], ['book', [[[0, 1, 2], [1, 0, 3], [0, 1, 4]]], 'non-manifold'], ['flipped pair', [[[0, 1, 2], [0, 1, 3]]], [True, [1]]], ['disk with two flips', [[[0, 1, 2], [0, 3, 2], [0, 3, 4], [0, 5, 4], [0, 5, 1]]], [True, [1, 3]]], ['two components second flipped', [[[0, 2, 1], [0, 1, 3], [1, 2, 3], [0, 3, 2], [4, 5, 6], [4, 5, 7]]], [True, [5]]], ['cube one flipped', [[[0, 3, 2, 1], [4, 5, 6, 7], [0, 4, 5, 1], [1, 2, 6, 5], [2, 3, 7, 6], [3, 0, 4, 7]]], [True, [2]]], ['annulus', [[[0, 3, 4, 1], [1, 4, 5, 2], [2, 5, 3, 0]]], [True, []]]], [['mobius', [[[0, 3, 4, 1], [1, 4, 5, 2], [2, 5, 0, 3]]], [False, []]], ['disk with two flips', [[[0, 1, 2], [0, 3, 2], [0, 3, 4], [0, 5, 4], [0, 5, 1]]], [True, [1, 3]]], ['cube one flipped', [[[0, 3, 2, 1], [4, 5, 6, 7], [0, 4, 5, 1], [1, 2, 6, 5], [2, 3, 7, 6], [3, 0, 4, 7]]], [True, [2]]], ['annulus', [[[0, 3, 4, 1], [1, 4, 5, 2], [2, 5, 3, 0]]], [True, []]], ['chain of flips', [[[0, 1, 2], [1, 2, 3], [2, 3, 4], [3, 4, 5]]], [True, [1, 3]]], ['quad grid', [[[0, 1, 4, 3], [1, 2, 5, 4], [3, 4, 7, 6], [4, 5, 8, 7]]], [True, []]], ['second component consistent', [[[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 5], [0, 5, 1], [10, 11, 12], [10, 11, 13]]], [True, [6]]]], [['consistent tetrahedron', [[[0, 2, 1], [0, 1, 3], [1, 2, 3], [0, 3, 2]]], [True, []]], ['one flipped face', [[[0, 2, 1], [0, 3, 1], [1, 2, 3], [0, 3, 2]]], [True, [1]]], ['mobius', [[[0, 3, 4, 1], [1, 4, 5, 2], [2, 5, 0, 3]]], [False, []]], ['flipped pair', [[[0, 1, 2], [0, 1, 3]]], [True, [1]]], ['two components second flipped', [[[0, 2, 1], [0, 1, 3], [1, 2, 3], [0, 3, 2], [4, 5, 6], [4, 5, 7]]], [True, [5]]], ['quad grid', [[[0, 1, 4, 3], [1, 2, 5, 4], [3, 4, 7, 6], [4, 5, 8, 7]]], [True, []]], ['second component consistent', [[[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 5], [0, 5, 1], [10, 11, 12], [10, 11, 13]]], [True, [6]]]], [['one flipped face', [[[0, 2, 1], [0, 3, 1], [1, 2, 3], [0, 3, 2]]], [True, [1]]], ['mobius', [[[0, 3, 4, 1], [1, 4, 5, 2], [2, 5, 0, 3]]], [False, []]], ['projective plane', [[[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 5], [0, 5, 1], [1, 2, 4], [2, 3, 5], [3, 4, 1], [4, 5, 2], [5, 1, 3]]], [False, []]], ['book', [[[0, 1, 2], [1, 0, 3], [0, 1, 4]]], 'non-manifold'], ['flipped pair', [[[0, 1, 2], [0, 1, 3]]], [True, [1]]], ['disk with two flips', [[[0, 1, 2], [0, 3, 2], [0, 3, 4], [0, 5, 4], [0, 5, 1]]], [True, [1, 3]]], ['cube one flipped', [[[0, 3, 2, 1], [4, 5, 6, 7], [0, 4, 5, 1], [1, 2, 6, 5], [2, 3, 7, 6], [3, 0, 4, 7]]], [True, [2]]]]]
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)

source:
"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(x):
    faces=x
    edge_faces={}
    for fi,f in enumerate(faces):
        n=len(f)
        for i in range(n):
            a,b=f[i],f[(i+1)%n]
            edge_faces.setdefault((min(a,b),max(a,b)),[]).append((fi,a,b))
    if any(len(v)>2 for v in edge_faces.values()): return 'non-manifold'
    flip=[None]*len(faces)
    for seed in range(len(faces)):
        if flip[seed] is not None: continue
        flip[seed]=0
        queue=[seed]
        while queue:
            fi=queue.pop(0)
            f=faces[fi]
            n=len(f)
            for i in range(n):
                a,b=f[i],f[(i+1)%n]
                for gj,c,d in edge_faces[(min(a,b),max(a,b))]:
                    if gj==fi: continue
                    same=1 if (c,d)==(a,b) and flip[fi]==0 else 0
                    want=flip[fi]^same
                    if flip[gj] is None:
                        flip[gj]=want
                        queue.append(gj)
                    elif flip[gj]!=want:
                        return [False,[]]
    return [True,[i for i in range(len(faces)) if flip[i]]]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['consistent tetrahedron', [[[0, 2, 1], [0, 1, 3], [1, 2, 3], [0, 3, 2]]], [True, []]], ['one flipped face', [[[0, 2, 1], [0, 3, 1], [1, 2, 3], [0, 3, 2]]], [True, [1]]], ['mobius', [[[0, 3, 4, 1], [1, 4, 5, 2], [2, 5, 0, 3]]], [False, []]], ['projective plane', [[[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 5], [0, 5, 1], [1, 2, 4], [2, 3, 5], [3, 4, 1], [4, 5, 2], [5, 1, 3]]], [False, []]], ['book', [[[0, 1, 2], [1, 0, 3], [0, 1, 4]]], 'non-manifold'], ['flipped pair', [[[0, 1, 2], [0, 1, 3]]], [True, [1]]], ['disk with two flips', [[[0, 1, 2], [0, 3, 2], [0, 3, 4], [0, 5, 4], [0, 5, 1]]], [True, [1, 3]]]], [['one flipped face', [[[0, 2, 1], [0, 3, 1], [1, 2, 3], [0, 3, 2]]], [True, [1]]], ['book', [[[0, 1, 2], [1, 0, 3], [0, 1, 4]]], 'non-manifold'], ['flipped pair', [[[0, 1, 2], [0, 1, 3]]], [True, [1]]], ['disk with two flips', [[[0, 1, 2], [0, 3, 2], [0, 3, 4], [0, 5, 4], [0, 5, 1]]], [True, [1, 3]]], ['two components second flipped', [[[0, 2, 1], [0, 1, 3], [1, 2, 3], [0, 3, 2], [4, 5, 6], [4, 5, 7]]], [True, [5]]], ['cube one flipped', [[[0, 3, 2, 1], [4, 5, 6, 7], [0, 4, 5, 1], [1, 2, 6, 5], [2, 3, 7, 6], [3, 0, 4, 7]]], [True, [2]]], ['annulus', [[[0, 3, 4, 1], [1, 4, 5, 2], [2, 5, 3, 0]]], [True, []]]], [['mobius', [[[0, 3, 4, 1], [1, 4, 5, 2], [2, 5, 0, 3]]], [False, []]], ['disk with two flips', [[[0, 1, 2], [0, 3, 2], [0, 3, 4], [0, 5, 4], [0, 5, 1]]], [True, [1, 3]]], ['cube one flipped', [[[0, 3, 2, 1], [4, 5, 6, 7], [0, 4, 5, 1], [1, 2, 6, 5], [2, 3, 7, 6], [3, 0, 4, 7]]], [True, [2]]], ['annulus', [[[0, 3, 4, 1], [1, 4, 5, 2], [2, 5, 3, 0]]], [True, []]], ['chain of flips', [[[0, 1, 2], [1, 2, 3], [2, 3, 4], [3, 4, 5]]], [True, [1, 3]]], ['quad grid', [[[0, 1, 4, 3], [1, 2, 5, 4], [3, 4, 7, 6], [4, 5, 8, 7]]], [True, []]], ['second component consistent', [[[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 5], [0, 5, 1], [10, 11, 12], [10, 11, 13]]], [True, [6]]]], [['consistent tetrahedron', [[[0, 2, 1], [0, 1, 3], [1, 2, 3], [0, 3, 2]]], [True, []]], ['one flipped face', [[[0, 2, 1], [0, 3, 1], [1, 2, 3], [0, 3, 2]]], [True, [1]]], ['mobius', [[[0, 3, 4, 1], [1, 4, 5, 2], [2, 5, 0, 3]]], [False, []]], ['flipped pair', [[[0, 1, 2], [0, 1, 3]]], [True, [1]]], ['two components second flipped', [[[0, 2, 1], [0, 1, 3], [1, 2, 3], [0, 3, 2], [4, 5, 6], [4, 5, 7]]], [True, [5]]], ['quad grid', [[[0, 1, 4, 3], [1, 2, 5, 4], [3, 4, 7, 6], [4, 5, 8, 7]]], [True, []]], ['second component consistent', [[[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 5], [0, 5, 1], [10, 11, 12], [10, 11, 13]]], [True, [6]]]], [['one flipped face', [[[0, 2, 1], [0, 3, 1], [1, 2, 3], [0, 3, 2]]], [True, [1]]], ['mobius', [[[0, 3, 4, 1], [1, 4, 5, 2], [2, 5, 0, 3]]], [False, []]], ['projective plane', [[[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 5], [0, 5, 1], [1, 2, 4], [2, 3, 5], [3, 4, 1], [4, 5, 2], [5, 1, 3]]], [False, []]], ['book', [[[0, 1, 2], [1, 0, 3], [0, 1, 4]]], 'non-manifold'], ['flipped pair', [[[0, 1, 2], [0, 1, 3]]], [True, [1]]], ['disk with two flips', [[[0, 1, 2], [0, 3, 2], [0, 3, 4], [0, 5, 4], [0, 5, 1]]], [True, [1, 3]]], ['cube one flipped', [[[0, 3, 2, 1], [4, 5, 6, 7], [0, 4, 5, 1], [1, 2, 6, 5], [2, 3, 7, 6], [3, 0, 4, 7]]], [True, [2]]]]]
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)

prompt:
Consistent neighbours are flipped and a consistent mesh reports flips everywhere.

Input: polygon faces. If any undirected edge has more than two incident faces return "non-manifold". Otherwise propagate orientation by breadth-first search from the lowest unvisited face of each component (that seed keeps its orientation). A neighbour across an edge used in the same direction must have the opposite flip state. Any conflict returns [false, []], else [true, sorted indices of faces to flip].

split: open-access


broken_source:
"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(x):
    faces=x
    edge_faces={}
    for fi,f in enumerate(faces):
        n=len(f)
        for i in range(n):
            a,b=f[i],f[(i+1)%n]
            edge_faces.setdefault((min(a,b),max(a,b)),[]).append((fi,a,b))
    if any(len(v)>2 for v in edge_faces.values()): return 'non-manifold'
    flip=[None]*len(faces)
    for seed in range(len(faces)):
        if flip[seed] is not None: continue
        flip[seed]=0
        queue=[seed]
        while queue:
            fi=queue.pop(0)
            f=faces[fi]
            n=len(f)
            for i in range(n):
                a,b=f[i],f[(i+1)%n]
                for gj,c,d in edge_faces[(min(a,b),max(a,b))]:
                    if gj==fi: continue
                    same=1 if (c,d)==(a,b) else 0
                    want=same
                    if flip[gj] is None:
                        flip[gj]=want
                        queue.append(gj)
                    elif flip[gj]!=want:
                        return [False,[]]
    return [True,[i for i in range(len(faces)) if flip[i]]]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['consistent tetrahedron', [[[0, 2, 1], [0, 1, 3], [1, 2, 3], [0, 3, 2]]], [True, []]], ['one flipped face', [[[0, 2, 1], [0, 3, 1], [1, 2, 3], [0, 3, 2]]], [True, [1]]], ['mobius', [[[0, 3, 4, 1], [1, 4, 5, 2], [2, 5, 0, 3]]], [False, []]], ['projective plane', [[[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 5], [0, 5, 1], [1, 2, 4], [2, 3, 5], [3, 4, 1], [4, 5, 2], [5, 1, 3]]], [False, []]], ['book', [[[0, 1, 2], [1, 0, 3], [0, 1, 4]]], 'non-manifold'], ['flipped pair', [[[0, 1, 2], [0, 1, 3]]], [True, [1]]], ['disk with two flips', [[[0, 1, 2], [0, 3, 2], [0, 3, 4], [0, 5, 4], [0, 5, 1]]], [True, [1, 3]]]], [['projective plane', [[[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 5], [0, 5, 1], [1, 2, 4], [2, 3, 5], [3, 4, 1], [4, 5, 2], [5, 1, 3]]], [False, []]], ['book', [[[0, 1, 2], [1, 0, 3], [0, 1, 4]]], 'non-manifold'], ['flipped pair', [[[0, 1, 2], [0, 1, 3]]], [True, [1]]], ['disk with two flips', [[[0, 1, 2], [0, 3, 2], [0, 3, 4], [0, 5, 4], [0, 5, 1]]], [True, [1, 3]]], ['two components second flipped', [[[0, 2, 1], [0, 1, 3], [1, 2, 3], [0, 3, 2], [4, 5, 6], [4, 5, 7]]], [True, [5]]], ['cube one flipped', [[[0, 3, 2, 1], [4, 5, 6, 7], [0, 4, 5, 1], [1, 2, 6, 5], [2, 3, 7, 6], [3, 0, 4, 7]]], [True, [2]]], ['annulus', [[[0, 3, 4, 1], [1, 4, 5, 2], [2, 5, 3, 0]]], [True, []]]], [['disk with two flips', [[[0, 1, 2], [0, 3, 2], [0, 3, 4], [0, 5, 4], [0, 5, 1]]], [True, [1, 3]]], ['two components second flipped', [[[0, 2, 1], [0, 1, 3], [1, 2, 3], [0, 3, 2], [4, 5, 6], [4, 5, 7]]], [True, [5]]], ['cube one flipped', [[[0, 3, 2, 1], [4, 5, 6, 7], [0, 4, 5, 1], [1, 2, 6, 5], [2, 3, 7, 6], [3, 0, 4, 7]]], [True, [2]]], ['annulus', [[[0, 3, 4, 1], [1, 4, 5, 2], [2, 5, 3, 0]]], [True, []]], ['chain of flips', [[[0, 1, 2], [1, 2, 3], [2, 3, 4], [3, 4, 5]]], [True, [1, 3]]], ['quad grid', [[[0, 1, 4, 3], [1, 2, 5, 4], [3, 4, 7, 6], [4, 5, 8, 7]]], [True, []]], ['second component consistent', [[[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 5], [0, 5, 1], [10, 11, 12], [10, 11, 13]]], [True, [6]]]], [['consistent tetrahedron', [[[0, 2, 1], [0, 1, 3], [1, 2, 3], [0, 3, 2]]], [True, []]], ['one flipped face', [[[0, 2, 1], [0, 3, 1], [1, 2, 3], [0, 3, 2]]], [True, [1]]], ['mobius', [[[0, 3, 4, 1], [1, 4, 5, 2], [2, 5, 0, 3]]], [False, []]], ['two components second flipped', [[[0, 2, 1], [0, 1, 3], [1, 2, 3], [0, 3, 2], [4, 5, 6], [4, 5, 7]]], [True, [5]]], ['chain of flips', [[[0, 1, 2], [1, 2, 3], [2, 3, 4], [3, 4, 5]]], [True, [1, 3]]], ['quad grid', [[[0, 1, 4, 3], [1, 2, 5, 4], [3, 4, 7, 6], [4, 5, 8, 7]]], [True, []]], ['second component consistent', [[[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 5], [0, 5, 1], [10, 11, 12], [10, 11, 13]]], [True, [6]]]], [['consistent tetrahedron', [[[0, 2, 1], [0, 1, 3], [1, 2, 3], [0, 3, 2]]], [True, []]], ['one flipped face', [[[0, 2, 1], [0, 3, 1], [1, 2, 3], [0, 3, 2]]], [True, [1]]], ['mobius', [[[0, 3, 4, 1], [1, 4, 5, 2], [2, 5, 0, 3]]], [False, []]], ['projective plane', [[[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 5], [0, 5, 1], [1, 2, 4], [2, 3, 5], [3, 4, 1], [4, 5, 2], [5, 1, 3]]], [False, []]], ['book', [[[0, 1, 2], [1, 0, 3], [0, 1, 4]]], 'non-manifold'], ['flipped pair', [[[0, 1, 2], [0, 1, 3]]], [True, [1]]], ['cube one flipped', [[[0, 3, 2, 1], [4, 5, 6, 7], [0, 4, 5, 1], [1, 2, 6, 5], [2, 3, 7, 6], [3, 0, 4, 7]]], [True, [2]]]]]
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)

source:
"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(x):
    faces=x
    edge_faces={}
    for fi,f in enumerate(faces):
        n=len(f)
        for i in range(n):
            a,b=f[i],f[(i+1)%n]
            edge_faces.setdefault((min(a,b),max(a,b)),[]).append((fi,a,b))
    if any(len(v)>2 for v in edge_faces.values()): return 'non-manifold'
    flip=[None]*len(faces)
    for seed in range(len(faces)):
        if flip[seed] is not None: continue
        flip[seed]=0
        queue=[seed]
        while queue:
            fi=queue.pop(0)
            f=faces[fi]
            n=len(f)
            for i in range(n):
                a,b=f[i],f[(i+1)%n]
                for gj,c,d in edge_faces[(min(a,b),max(a,b))]:
                    if gj==fi: continue
                    same=1 if (c,d)==(a,b) else 0
                    want=flip[fi]|same
                    if flip[gj] is None:
                        flip[gj]=want
                        queue.append(gj)
                    elif flip[gj]!=want:
                        return [False,[]]
    return [True,[i for i in range(len(faces)) if flip[i]]]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['consistent tetrahedron', [[[0, 2, 1], [0, 1, 3], [1, 2, 3], [0, 3, 2]]], [True, []]], ['one flipped face', [[[0, 2, 1], [0, 3, 1], [1, 2, 3], [0, 3, 2]]], [True, [1]]], ['mobius', [[[0, 3, 4, 1], [1, 4, 5, 2], [2, 5, 0, 3]]], [False, []]], ['projective plane', [[[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 5], [0, 5, 1], [1, 2, 4], [2, 3, 5], [3, 4, 1], [4, 5, 2], [5, 1, 3]]], [False, []]], ['book', [[[0, 1, 2], [1, 0, 3], [0, 1, 4]]], 'non-manifold'], ['flipped pair', [[[0, 1, 2], [0, 1, 3]]], [True, [1]]], ['disk with two flips', [[[0, 1, 2], [0, 3, 2], [0, 3, 4], [0, 5, 4], [0, 5, 1]]], [True, [1, 3]]]], [['projective plane', [[[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 5], [0, 5, 1], [1, 2, 4], [2, 3, 5], [3, 4, 1], [4, 5, 2], [5, 1, 3]]], [False, []]], ['book', [[[0, 1, 2], [1, 0, 3], [0, 1, 4]]], 'non-manifold'], ['flipped pair', [[[0, 1, 2], [0, 1, 3]]], [True, [1]]], ['disk with two flips', [[[0, 1, 2], [0, 3, 2], [0, 3, 4], [0, 5, 4], [0, 5, 1]]], [True, [1, 3]]], ['two components second flipped', [[[0, 2, 1], [0, 1, 3], [1, 2, 3], [0, 3, 2], [4, 5, 6], [4, 5, 7]]], [True, [5]]], ['cube one flipped', [[[0, 3, 2, 1], [4, 5, 6, 7], [0, 4, 5, 1], [1, 2, 6, 5], [2, 3, 7, 6], [3, 0, 4, 7]]], [True, [2]]], ['annulus', [[[0, 3, 4, 1], [1, 4, 5, 2], [2, 5, 3, 0]]], [True, []]]], [['disk with two flips', [[[0, 1, 2], [0, 3, 2], [0, 3, 4], [0, 5, 4], [0, 5, 1]]], [True, [1, 3]]], ['two components second flipped', [[[0, 2, 1], [0, 1, 3], [1, 2, 3], [0, 3, 2], [4, 5, 6], [4, 5, 7]]], [True, [5]]], ['cube one flipped', [[[0, 3, 2, 1], [4, 5, 6, 7], [0, 4, 5, 1], [1, 2, 6, 5], [2, 3, 7, 6], [3, 0, 4, 7]]], [True, [2]]], ['annulus', [[[0, 3, 4, 1], [1, 4, 5, 2], [2, 5, 3, 0]]], [True, []]], ['chain of flips', [[[0, 1, 2], [1, 2, 3], [2, 3, 4], [3, 4, 5]]], [True, [1, 3]]], ['quad grid', [[[0, 1, 4, 3], [1, 2, 5, 4], [3, 4, 7, 6], [4, 5, 8, 7]]], [True, []]], ['second component consistent', [[[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 5], [0, 5, 1], [10, 11, 12], [10, 11, 13]]], [True, [6]]]], [['consistent tetrahedron', [[[0, 2, 1], [0, 1, 3], [1, 2, 3], [0, 3, 2]]], [True, []]], ['one flipped face', [[[0, 2, 1], [0, 3, 1], [1, 2, 3], [0, 3, 2]]], [True, [1]]], ['mobius', [[[0, 3, 4, 1], [1, 4, 5, 2], [2, 5, 0, 3]]], [False, []]], ['two components second flipped', [[[0, 2, 1], [0, 1, 3], [1, 2, 3], [0, 3, 2], [4, 5, 6], [4, 5, 7]]], [True, [5]]], ['chain of flips', [[[0, 1, 2], [1, 2, 3], [2, 3, 4], [3, 4, 5]]], [True, [1, 3]]], ['quad grid', [[[0, 1, 4, 3], [1, 2, 5, 4], [3, 4, 7, 6], [4, 5, 8, 7]]], [True, []]], ['second component consistent', [[[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 5], [0, 5, 1], [10, 11, 12], [10, 11, 13]]], [True, [6]]]], [['consistent tetrahedron', [[[0, 2, 1], [0, 1, 3], [1, 2, 3], [0, 3, 2]]], [True, []]], ['one flipped face', [[[0, 2, 1], [0, 3, 1], [1, 2, 3], [0, 3, 2]]], [True, [1]]], ['mobius', [[[0, 3, 4, 1], [1, 4, 5, 2], [2, 5, 0, 3]]], [False, []]], ['projective plane', [[[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 5], [0, 5, 1], [1, 2, 4], [2, 3, 5], [3, 4, 1], [4, 5, 2], [5, 1, 3]]], [False, []]], ['book', [[[0, 1, 2], [1, 0, 3], [0, 1, 4]]], 'non-manifold'], ['flipped pair', [[[0, 1, 2], [0, 1, 3]]], [True, [1]]], ['cube one flipped', [[[0, 3, 2, 1], [4, 5, 6, 7], [0, 4, 5, 1], [1, 2, 6, 5], [2, 3, 7, 6], [3, 0, 4, 7]]], [True, [2]]]]]
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)

prompt:
Chains of alternately oriented faces are repaired incorrectly after the first flip.

Input: polygon faces. If any undirected edge has more than two incident faces return "non-manifold". Otherwise propagate orientation by breadth-first search from the lowest unvisited face of each component (that seed keeps its orientation). A neighbour across an edge used in the same direction must have the opposite flip state. Any conflict returns [false, []], else [true, sorted indices of faces to flip].

split: open-access


broken_source:
"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(x):
    faces=x
    edge_faces={}
    for fi,f in enumerate(faces):
        n=len(f)
        for i in range(n):
            a,b=f[i],f[(i+1)%n]
            edge_faces.setdefault((min(a,b),max(a,b)),[]).append((fi,a,b))
    if any(len(v)>2 for v in edge_faces.values()): return 'non-manifold'
    flip=[None]*len(faces)
    for seed in range(len(faces)):
        if flip[seed] is not None: continue
        flip[seed]=0
        queue=[seed]
        while queue:
            fi=queue.pop(0)
            f=faces[fi]
            n=len(f)
            for i in range(n):
                a,b=f[i],f[(i+1)%n]
                for gj,c,d in edge_faces[(min(a,b),max(a,b))]:
                    if gj==fi: continue
                    same=1 if (c,d)==(a,b) else 0
                    want=flip[fi]^same
                    if flip[gj] is None:
                        flip[gj]=want
                        queue.append(gj)
    return [True,[i for i in range(len(faces)) if flip[i]]]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['consistent tetrahedron', [[[0, 2, 1], [0, 1, 3], [1, 2, 3], [0, 3, 2]]], [True, []]], ['one flipped face', [[[0, 2, 1], [0, 3, 1], [1, 2, 3], [0, 3, 2]]], [True, [1]]], ['mobius', [[[0, 3, 4, 1], [1, 4, 5, 2], [2, 5, 0, 3]]], [False, []]], ['projective plane', [[[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 5], [0, 5, 1], [1, 2, 4], [2, 3, 5], [3, 4, 1], [4, 5, 2], [5, 1, 3]]], [False, []]], ['book', [[[0, 1, 2], [1, 0, 3], [0, 1, 4]]], 'non-manifold'], ['flipped pair', [[[0, 1, 2], [0, 1, 3]]], [True, [1]]], ['disk with two flips', [[[0, 1, 2], [0, 3, 2], [0, 3, 4], [0, 5, 4], [0, 5, 1]]], [True, [1, 3]]]], [['projective plane', [[[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 5], [0, 5, 1], [1, 2, 4], [2, 3, 5], [3, 4, 1], [4, 5, 2], [5, 1, 3]]], [False, []]], ['book', [[[0, 1, 2], [1, 0, 3], [0, 1, 4]]], 'non-manifold'], ['flipped pair', [[[0, 1, 2], [0, 1, 3]]], [True, [1]]], ['disk with two flips', [[[0, 1, 2], [0, 3, 2], [0, 3, 4], [0, 5, 4], [0, 5, 1]]], [True, [1, 3]]], ['two components second flipped', [[[0, 2, 1], [0, 1, 3], [1, 2, 3], [0, 3, 2], [4, 5, 6], [4, 5, 7]]], [True, [5]]], ['cube one flipped', [[[0, 3, 2, 1], [4, 5, 6, 7], [0, 4, 5, 1], [1, 2, 6, 5], [2, 3, 7, 6], [3, 0, 4, 7]]], [True, [2]]], ['annulus', [[[0, 3, 4, 1], [1, 4, 5, 2], [2, 5, 3, 0]]], [True, []]]], [['mobius', [[[0, 3, 4, 1], [1, 4, 5, 2], [2, 5, 0, 3]]], [False, []]], ['two components second flipped', [[[0, 2, 1], [0, 1, 3], [1, 2, 3], [0, 3, 2], [4, 5, 6], [4, 5, 7]]], [True, [5]]], ['cube one flipped', [[[0, 3, 2, 1], [4, 5, 6, 7], [0, 4, 5, 1], [1, 2, 6, 5], [2, 3, 7, 6], [3, 0, 4, 7]]], [True, [2]]], ['annulus', [[[0, 3, 4, 1], [1, 4, 5, 2], [2, 5, 3, 0]]], [True, []]], ['chain of flips', [[[0, 1, 2], [1, 2, 3], [2, 3, 4], [3, 4, 5]]], [True, [1, 3]]], ['quad grid', [[[0, 1, 4, 3], [1, 2, 5, 4], [3, 4, 7, 6], [4, 5, 8, 7]]], [True, []]], ['second component consistent', [[[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 5], [0, 5, 1], [10, 11, 12], [10, 11, 13]]], [True, [6]]]], [['consistent tetrahedron', [[[0, 2, 1], [0, 1, 3], [1, 2, 3], [0, 3, 2]]], [True, []]], ['one flipped face', [[[0, 2, 1], [0, 3, 1], [1, 2, 3], [0, 3, 2]]], [True, [1]]], ['mobius', [[[0, 3, 4, 1], [1, 4, 5, 2], [2, 5, 0, 3]]], [False, []]], ['projective plane', [[[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 5], [0, 5, 1], [1, 2, 4], [2, 3, 5], [3, 4, 1], [4, 5, 2], [5, 1, 3]]], [False, []]], ['chain of flips', [[[0, 1, 2], [1, 2, 3], [2, 3, 4], [3, 4, 5]]], [True, [1, 3]]], ['quad grid', [[[0, 1, 4, 3], [1, 2, 5, 4], [3, 4, 7, 6], [4, 5, 8, 7]]], [True, []]], ['second component consistent', [[[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 5], [0, 5, 1], [10, 11, 12], [10, 11, 13]]], [True, [6]]]], [['consistent tetrahedron', [[[0, 2, 1], [0, 1, 3], [1, 2, 3], [0, 3, 2]]], [True, []]], ['one flipped face', [[[0, 2, 1], [0, 3, 1], [1, 2, 3], [0, 3, 2]]], [True, [1]]], ['mobius', [[[0, 3, 4, 1], [1, 4, 5, 2], [2, 5, 0, 3]]], [False, []]], ['projective plane', [[[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 5], [0, 5, 1], [1, 2, 4], [2, 3, 5], [3, 4, 1], [4, 5, 2], [5, 1, 3]]], [False, []]], ['book', [[[0, 1, 2], [1, 0, 3], [0, 1, 4]]], 'non-manifold'], ['flipped pair', [[[0, 1, 2], [0, 1, 3]]], [True, [1]]], ['disk with two flips', [[[0, 1, 2], [0, 3, 2], [0, 3, 4], [0, 5, 4], [0, 5, 1]]], [True, [1, 3]]]]]
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)

source:
"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(x):
    faces=x
    edge_faces={}
    for fi,f in enumerate(faces):
        n=len(f)
        for i in range(n):
            a,b=f[i],f[(i+1)%n]
            edge_faces.setdefault((min(a,b),max(a,b)),[]).append((fi,a,b))
    if any(len(v)>2 for v in edge_faces.values()): return 'non-manifold'
    flip=[None]*len(faces)
    for seed in range(len(faces)):
        if flip[seed] is not None: continue
        flip[seed]=0
        queue=[seed]
        while queue:
            fi=queue.pop(0)
            f=faces[fi]
            n=len(f)
            for i in range(n):
                a,b=f[i],f[(i+1)%n]
                for gj,c,d in edge_faces[(min(a,b),max(a,b))]:
                    if gj==fi: continue
                    same=1 if (c,d)==(a,b) else 0
                    want=flip[fi]^same
                    if flip[gj] is None:
                        flip[gj]=want
                        queue.append(gj)
                    elif flip[gj]!=want and gj==seed:
                        return [False,[]]
    return [True,[i for i in range(len(faces)) if flip[i]]]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['consistent tetrahedron', [[[0, 2, 1], [0, 1, 3], [1, 2, 3], [0, 3, 2]]], [True, []]], ['one flipped face', [[[0, 2, 1], [0, 3, 1], [1, 2, 3], [0, 3, 2]]], [True, [1]]], ['mobius', [[[0, 3, 4, 1], [1, 4, 5, 2], [2, 5, 0, 3]]], [False, []]], ['projective plane', [[[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 5], [0, 5, 1], [1, 2, 4], [2, 3, 5], [3, 4, 1], [4, 5, 2], [5, 1, 3]]], [False, []]], ['book', [[[0, 1, 2], [1, 0, 3], [0, 1, 4]]], 'non-manifold'], ['flipped pair', [[[0, 1, 2], [0, 1, 3]]], [True, [1]]], ['disk with two flips', [[[0, 1, 2], [0, 3, 2], [0, 3, 4], [0, 5, 4], [0, 5, 1]]], [True, [1, 3]]]], [['projective plane', [[[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 5], [0, 5, 1], [1, 2, 4], [2, 3, 5], [3, 4, 1], [4, 5, 2], [5, 1, 3]]], [False, []]], ['book', [[[0, 1, 2], [1, 0, 3], [0, 1, 4]]], 'non-manifold'], ['flipped pair', [[[0, 1, 2], [0, 1, 3]]], [True, [1]]], ['disk with two flips', [[[0, 1, 2], [0, 3, 2], [0, 3, 4], [0, 5, 4], [0, 5, 1]]], [True, [1, 3]]], ['two components second flipped', [[[0, 2, 1], [0, 1, 3], [1, 2, 3], [0, 3, 2], [4, 5, 6], [4, 5, 7]]], [True, [5]]], ['cube one flipped', [[[0, 3, 2, 1], [4, 5, 6, 7], [0, 4, 5, 1], [1, 2, 6, 5], [2, 3, 7, 6], [3, 0, 4, 7]]], [True, [2]]], ['annulus', [[[0, 3, 4, 1], [1, 4, 5, 2], [2, 5, 3, 0]]], [True, []]]], [['mobius', [[[0, 3, 4, 1], [1, 4, 5, 2], [2, 5, 0, 3]]], [False, []]], ['two components second flipped', [[[0, 2, 1], [0, 1, 3], [1, 2, 3], [0, 3, 2], [4, 5, 6], [4, 5, 7]]], [True, [5]]], ['cube one flipped', [[[0, 3, 2, 1], [4, 5, 6, 7], [0, 4, 5, 1], [1, 2, 6, 5], [2, 3, 7, 6], [3, 0, 4, 7]]], [True, [2]]], ['annulus', [[[0, 3, 4, 1], [1, 4, 5, 2], [2, 5, 3, 0]]], [True, []]], ['chain of flips', [[[0, 1, 2], [1, 2, 3], [2, 3, 4], [3, 4, 5]]], [True, [1, 3]]], ['quad grid', [[[0, 1, 4, 3], [1, 2, 5, 4], [3, 4, 7, 6], [4, 5, 8, 7]]], [True, []]], ['second component consistent', [[[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 5], [0, 5, 1], [10, 11, 12], [10, 11, 13]]], [True, [6]]]], [['consistent tetrahedron', [[[0, 2, 1], [0, 1, 3], [1, 2, 3], [0, 3, 2]]], [True, []]], ['one flipped face', [[[0, 2, 1], [0, 3, 1], [1, 2, 3], [0, 3, 2]]], [True, [1]]], ['mobius', [[[0, 3, 4, 1], [1, 4, 5, 2], [2, 5, 0, 3]]], [False, []]], ['projective plane', [[[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 5], [0, 5, 1], [1, 2, 4], [2, 3, 5], [3, 4, 1], [4, 5, 2], [5, 1, 3]]], [False, []]], ['chain of flips', [[[0, 1, 2], [1, 2, 3], [2, 3, 4], [3, 4, 5]]], [True, [1, 3]]], ['quad grid', [[[0, 1, 4, 3], [1, 2, 5, 4], [3, 4, 7, 6], [4, 5, 8, 7]]], [True, []]], ['second component consistent', [[[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 5], [0, 5, 1], [10, 11, 12], [10, 11, 13]]], [True, [6]]]], [['consistent tetrahedron', [[[0, 2, 1], [0, 1, 3], [1, 2, 3], [0, 3, 2]]], [True, []]], ['one flipped face', [[[0, 2, 1], [0, 3, 1], [1, 2, 3], [0, 3, 2]]], [True, [1]]], ['mobius', [[[0, 3, 4, 1], [1, 4, 5, 2], [2, 5, 0, 3]]], [False, []]], ['projective plane', [[[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 5], [0, 5, 1], [1, 2, 4], [2, 3, 5], [3, 4, 1], [4, 5, 2], [5, 1, 3]]], [False, []]], ['book', [[[0, 1, 2], [1, 0, 3], [0, 1, 4]]], 'non-manifold'], ['flipped pair', [[[0, 1, 2], [0, 1, 3]]], [True, [1]]], ['disk with two flips', [[[0, 1, 2], [0, 3, 2], [0, 3, 4], [0, 5, 4], [0, 5, 1]]], [True, [1, 3]]]]]
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)

prompt:
Moebius strips and projective planes are reported orientable.

Input: polygon faces. If any undirected edge has more than two incident faces return "non-manifold". Otherwise propagate orientation by breadth-first search from the lowest unvisited face of each component (that seed keeps its orientation). A neighbour across an edge used in the same direction must have the opposite flip state. Any conflict returns [false, []], else [true, sorted indices of faces to flip].

split: open-access


broken_source:
"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(x):
    faces=x
    edge_faces={}
    for fi,f in enumerate(faces):
        n=len(f)
        for i in range(n):
            a,b=f[i],f[(i+1)%n]
            edge_faces.setdefault((min(a,b),max(a,b)),[]).append((fi,a,b))
    if any(len(v)>2 for v in edge_faces.values()): return 'non-manifold'
    flip=[None]*len(faces)
    for seed in range(len(faces)):
        if flip[seed] is not None: continue
        flip[seed]=1
        queue=[seed]
        while queue:
            fi=queue.pop(0)
            f=faces[fi]
            n=len(f)
            for i in range(n):
                a,b=f[i],f[(i+1)%n]
                for gj,c,d in edge_faces[(min(a,b),max(a,b))]:
                    if gj==fi: continue
                    same=1 if (c,d)==(a,b) else 0
                    want=flip[fi]^same
                    if flip[gj] is None:
                        flip[gj]=want
                        queue.append(gj)
                    elif flip[gj]!=want:
                        return [False,[]]
    return [True,[i for i in range(len(faces)) if flip[i]]]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['consistent tetrahedron', [[[0, 2, 1], [0, 1, 3], [1, 2, 3], [0, 3, 2]]], [True, []]], ['one flipped face', [[[0, 2, 1], [0, 3, 1], [1, 2, 3], [0, 3, 2]]], [True, [1]]], ['mobius', [[[0, 3, 4, 1], [1, 4, 5, 2], [2, 5, 0, 3]]], [False, []]], ['projective plane', [[[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 5], [0, 5, 1], [1, 2, 4], [2, 3, 5], [3, 4, 1], [4, 5, 2], [5, 1, 3]]], [False, []]], ['book', [[[0, 1, 2], [1, 0, 3], [0, 1, 4]]], 'non-manifold'], ['flipped pair', [[[0, 1, 2], [0, 1, 3]]], [True, [1]]], ['second component consistent', [[[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 5], [0, 5, 1], [10, 11, 12], [10, 11, 13]]], [True, [6]]]], [['one flipped face', [[[0, 2, 1], [0, 3, 1], [1, 2, 3], [0, 3, 2]]], [True, [1]]], ['book', [[[0, 1, 2], [1, 0, 3], [0, 1, 4]]], 'non-manifold'], ['flipped pair', [[[0, 1, 2], [0, 1, 3]]], [True, [1]]], ['disk with two flips', [[[0, 1, 2], [0, 3, 2], [0, 3, 4], [0, 5, 4], [0, 5, 1]]], [True, [1, 3]]], ['two components second flipped', [[[0, 2, 1], [0, 1, 3], [1, 2, 3], [0, 3, 2], [4, 5, 6], [4, 5, 7]]], [True, [5]]], ['cube one flipped', [[[0, 3, 2, 1], [4, 5, 6, 7], [0, 4, 5, 1], [1, 2, 6, 5], [2, 3, 7, 6], [3, 0, 4, 7]]], [True, [2]]], ['second component consistent', [[[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 5], [0, 5, 1], [10, 11, 12], [10, 11, 13]]], [True, [6]]]], [['flipped pair', [[[0, 1, 2], [0, 1, 3]]], [True, [1]]], ['two components second flipped', [[[0, 2, 1], [0, 1, 3], [1, 2, 3], [0, 3, 2], [4, 5, 6], [4, 5, 7]]], [True, [5]]], ['cube one flipped', [[[0, 3, 2, 1], [4, 5, 6, 7], [0, 4, 5, 1], [1, 2, 6, 5], [2, 3, 7, 6], [3, 0, 4, 7]]], [True, [2]]], ['annulus', [[[0, 3, 4, 1], [1, 4, 5, 2], [2, 5, 3, 0]]], [True, []]], ['chain of flips', [[[0, 1, 2], [1, 2, 3], [2, 3, 4], [3, 4, 5]]], [True, [1, 3]]], ['quad grid', [[[0, 1, 4, 3], [1, 2, 5, 4], [3, 4, 7, 6], [4, 5, 8, 7]]], [True, []]], ['second component consistent', [[[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 5], [0, 5, 1], [10, 11, 12], [10, 11, 13]]], [True, [6]]]], [['consistent tetrahedron', [[[0, 2, 1], [0, 1, 3], [1, 2, 3], [0, 3, 2]]], [True, []]], ['one flipped face', [[[0, 2, 1], [0, 3, 1], [1, 2, 3], [0, 3, 2]]], [True, [1]]], ['mobius', [[[0, 3, 4, 1], [1, 4, 5, 2], [2, 5, 0, 3]]], [False, []]], ['disk with two flips', [[[0, 1, 2], [0, 3, 2], [0, 3, 4], [0, 5, 4], [0, 5, 1]]], [True, [1, 3]]], ['chain of flips', [[[0, 1, 2], [1, 2, 3], [2, 3, 4], [3, 4, 5]]], [True, [1, 3]]], ['quad grid', [[[0, 1, 4, 3], [1, 2, 5, 4], [3, 4, 7, 6], [4, 5, 8, 7]]], [True, []]], ['second component consistent', [[[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 5], [0, 5, 1], [10, 11, 12], [10, 11, 13]]], [True, [6]]]], [['one flipped face', [[[0, 2, 1], [0, 3, 1], [1, 2, 3], [0, 3, 2]]], [True, [1]]], ['mobius', [[[0, 3, 4, 1], [1, 4, 5, 2], [2, 5, 0, 3]]], [False, []]], ['projective plane', [[[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 5], [0, 5, 1], [1, 2, 4], [2, 3, 5], [3, 4, 1], [4, 5, 2], [5, 1, 3]]], [False, []]], ['book', [[[0, 1, 2], [1, 0, 3], [0, 1, 4]]], 'non-manifold'], ['flipped pair', [[[0, 1, 2], [0, 1, 3]]], [True, [1]]], ['two components second flipped', [[[0, 2, 1], [0, 1, 3], [1, 2, 3], [0, 3, 2], [4, 5, 6], [4, 5, 7]]], [True, [5]]], ['second component consistent', [[[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 5], [0, 5, 1], [10, 11, 12], [10, 11, 13]]], [True, [6]]]]]
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)

source:
"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(x):
    faces=x
    edge_faces={}
    for fi,f in enumerate(faces):
        n=len(f)
        for i in range(n):
            a,b=f[i],f[(i+1)%n]
            edge_faces.setdefault((min(a,b),max(a,b)),[]).append((fi,a,b))
    if any(len(v)>2 for v in edge_faces.values()): return 'non-manifold'
    flip=[None]*len(faces)
    for seed in range(len(faces)):
        if flip[seed] is not None: continue
        flip[seed]=seed%2
        queue=[seed]
        while queue:
            fi=queue.pop(0)
            f=faces[fi]
            n=len(f)
            for i in range(n):
                a,b=f[i],f[(i+1)%n]
                for gj,c,d in edge_faces[(min(a,b),max(a,b))]:
                    if gj==fi: continue
                    same=1 if (c,d)==(a,b) else 0
                    want=flip[fi]^same
                    if flip[gj] is None:
                        flip[gj]=want
                        queue.append(gj)
                    elif flip[gj]!=want:
                        return [False,[]]
    return [True,[i for i in range(len(faces)) if flip[i]]]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['consistent tetrahedron', [[[0, 2, 1], [0, 1, 3], [1, 2, 3], [0, 3, 2]]], [True, []]], ['one flipped face', [[[0, 2, 1], [0, 3, 1], [1, 2, 3], [0, 3, 2]]], [True, [1]]], ['mobius', [[[0, 3, 4, 1], [1, 4, 5, 2], [2, 5, 0, 3]]], [False, []]], ['projective plane', [[[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 5], [0, 5, 1], [1, 2, 4], [2, 3, 5], [3, 4, 1], [4, 5, 2], [5, 1, 3]]], [False, []]], ['book', [[[0, 1, 2], [1, 0, 3], [0, 1, 4]]], 'non-manifold'], ['flipped pair', [[[0, 1, 2], [0, 1, 3]]], [True, [1]]], ['second component consistent', [[[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 5], [0, 5, 1], [10, 11, 12], [10, 11, 13]]], [True, [6]]]], [['one flipped face', [[[0, 2, 1], [0, 3, 1], [1, 2, 3], [0, 3, 2]]], [True, [1]]], ['book', [[[0, 1, 2], [1, 0, 3], [0, 1, 4]]], 'non-manifold'], ['flipped pair', [[[0, 1, 2], [0, 1, 3]]], [True, [1]]], ['disk with two flips', [[[0, 1, 2], [0, 3, 2], [0, 3, 4], [0, 5, 4], [0, 5, 1]]], [True, [1, 3]]], ['two components second flipped', [[[0, 2, 1], [0, 1, 3], [1, 2, 3], [0, 3, 2], [4, 5, 6], [4, 5, 7]]], [True, [5]]], ['cube one flipped', [[[0, 3, 2, 1], [4, 5, 6, 7], [0, 4, 5, 1], [1, 2, 6, 5], [2, 3, 7, 6], [3, 0, 4, 7]]], [True, [2]]], ['second component consistent', [[[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 5], [0, 5, 1], [10, 11, 12], [10, 11, 13]]], [True, [6]]]], [['flipped pair', [[[0, 1, 2], [0, 1, 3]]], [True, [1]]], ['two components second flipped', [[[0, 2, 1], [0, 1, 3], [1, 2, 3], [0, 3, 2], [4, 5, 6], [4, 5, 7]]], [True, [5]]], ['cube one flipped', [[[0, 3, 2, 1], [4, 5, 6, 7], [0, 4, 5, 1], [1, 2, 6, 5], [2, 3, 7, 6], [3, 0, 4, 7]]], [True, [2]]], ['annulus', [[[0, 3, 4, 1], [1, 4, 5, 2], [2, 5, 3, 0]]], [True, []]], ['chain of flips', [[[0, 1, 2], [1, 2, 3], [2, 3, 4], [3, 4, 5]]], [True, [1, 3]]], ['quad grid', [[[0, 1, 4, 3], [1, 2, 5, 4], [3, 4, 7, 6], [4, 5, 8, 7]]], [True, []]], ['second component consistent', [[[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 5], [0, 5, 1], [10, 11, 12], [10, 11, 13]]], [True, [6]]]], [['consistent tetrahedron', [[[0, 2, 1], [0, 1, 3], [1, 2, 3], [0, 3, 2]]], [True, []]], ['one flipped face', [[[0, 2, 1], [0, 3, 1], [1, 2, 3], [0, 3, 2]]], [True, [1]]], ['mobius', [[[0, 3, 4, 1], [1, 4, 5, 2], [2, 5, 0, 3]]], [False, []]], ['disk with two flips', [[[0, 1, 2], [0, 3, 2], [0, 3, 4], [0, 5, 4], [0, 5, 1]]], [True, [1, 3]]], ['chain of flips', [[[0, 1, 2], [1, 2, 3], [2, 3, 4], [3, 4, 5]]], [True, [1, 3]]], ['quad grid', [[[0, 1, 4, 3], [1, 2, 5, 4], [3, 4, 7, 6], [4, 5, 8, 7]]], [True, []]], ['second component consistent', [[[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 5], [0, 5, 1], [10, 11, 12], [10, 11, 13]]], [True, [6]]]], [['one flipped face', [[[0, 2, 1], [0, 3, 1], [1, 2, 3], [0, 3, 2]]], [True, [1]]], ['mobius', [[[0, 3, 4, 1], [1, 4, 5, 2], [2, 5, 0, 3]]], [False, []]], ['projective plane', [[[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 5], [0, 5, 1], [1, 2, 4], [2, 3, 5], [3, 4, 1], [4, 5, 2], [5, 1, 3]]], [False, []]], ['book', [[[0, 1, 2], [1, 0, 3], [0, 1, 4]]], 'non-manifold'], ['flipped pair', [[[0, 1, 2], [0, 1, 3]]], [True, [1]]], ['two components second flipped', [[[0, 2, 1], [0, 1, 3], [1, 2, 3], [0, 3, 2], [4, 5, 6], [4, 5, 7]]], [True, [5]]], ['second component consistent', [[[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 5], [0, 5, 1], [10, 11, 12], [10, 11, 13]]], [True, [6]]]]]
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)

prompt:
Every face of every component is reported as needing a flip.

Input: polygon faces. If any undirected edge has more than two incident faces return "non-manifold". Otherwise propagate orientation by breadth-first search from the lowest unvisited face of each component (that seed keeps its orientation). A neighbour across an edge used in the same direction must have the opposite flip state. Any conflict returns [false, []], else [true, sorted indices of faces to flip].

split: open-access


broken_source:
"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(x):
    faces=x
    edge_faces={}
    for fi,f in enumerate(faces):
        n=len(f)
        for i in range(n):
            a,b=f[i],f[(i+1)%n]
            edge_faces.setdefault((min(a,b),max(a,b)),[]).append((fi,a,b))
    if any(len(v)>3 for v in edge_faces.values()): return 'non-manifold'
    flip=[None]*len(faces)
    for seed in range(len(faces)):
        if flip[seed] is not None: continue
        flip[seed]=0
        queue=[seed]
        while queue:
            fi=queue.pop(0)
            f=faces[fi]
            n=len(f)
            for i in range(n):
                a,b=f[i],f[(i+1)%n]
                for gj,c,d in edge_faces[(min(a,b),max(a,b))]:
                    if gj==fi: continue
                    same=1 if (c,d)==(a,b) else 0
                    want=flip[fi]^same
                    if flip[gj] is None:
                        flip[gj]=want
                        queue.append(gj)
                    elif flip[gj]!=want:
                        return [False,[]]
    return [True,[i for i in range(len(faces)) if flip[i]]]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['consistent tetrahedron', [[[0, 2, 1], [0, 1, 3], [1, 2, 3], [0, 3, 2]]], [True, []]], ['one flipped face', [[[0, 2, 1], [0, 3, 1], [1, 2, 3], [0, 3, 2]]], [True, [1]]], ['mobius', [[[0, 3, 4, 1], [1, 4, 5, 2], [2, 5, 0, 3]]], [False, []]], ['projective plane', [[[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 5], [0, 5, 1], [1, 2, 4], [2, 3, 5], [3, 4, 1], [4, 5, 2], [5, 1, 3]]], [False, []]], ['book', [[[0, 1, 2], [1, 0, 3], [0, 1, 4]]], 'non-manifold'], ['flipped pair', [[[0, 1, 2], [0, 1, 3]]], [True, [1]]], ['disk with two flips', [[[0, 1, 2], [0, 3, 2], [0, 3, 4], [0, 5, 4], [0, 5, 1]]], [True, [1, 3]]]], [['one flipped face', [[[0, 2, 1], [0, 3, 1], [1, 2, 3], [0, 3, 2]]], [True, [1]]], ['book', [[[0, 1, 2], [1, 0, 3], [0, 1, 4]]], 'non-manifold'], ['flipped pair', [[[0, 1, 2], [0, 1, 3]]], [True, [1]]], ['disk with two flips', [[[0, 1, 2], [0, 3, 2], [0, 3, 4], [0, 5, 4], [0, 5, 1]]], [True, [1, 3]]], ['two components second flipped', [[[0, 2, 1], [0, 1, 3], [1, 2, 3], [0, 3, 2], [4, 5, 6], [4, 5, 7]]], [True, [5]]], ['cube one flipped', [[[0, 3, 2, 1], [4, 5, 6, 7], [0, 4, 5, 1], [1, 2, 6, 5], [2, 3, 7, 6], [3, 0, 4, 7]]], [True, [2]]], ['annulus', [[[0, 3, 4, 1], [1, 4, 5, 2], [2, 5, 3, 0]]], [True, []]]], [['mobius', [[[0, 3, 4, 1], [1, 4, 5, 2], [2, 5, 0, 3]]], [False, []]], ['book', [[[0, 1, 2], [1, 0, 3], [0, 1, 4]]], 'non-manifold'], ['cube one flipped', [[[0, 3, 2, 1], [4, 5, 6, 7], [0, 4, 5, 1], [1, 2, 6, 5], [2, 3, 7, 6], [3, 0, 4, 7]]], [True, [2]]], ['annulus', [[[0, 3, 4, 1], [1, 4, 5, 2], [2, 5, 3, 0]]], [True, []]], ['chain of flips', [[[0, 1, 2], [1, 2, 3], [2, 3, 4], [3, 4, 5]]], [True, [1, 3]]], ['quad grid', [[[0, 1, 4, 3], [1, 2, 5, 4], [3, 4, 7, 6], [4, 5, 8, 7]]], [True, []]], ['second component consistent', [[[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 5], [0, 5, 1], [10, 11, 12], [10, 11, 13]]], [True, [6]]]], [['consistent tetrahedron', [[[0, 2, 1], [0, 1, 3], [1, 2, 3], [0, 3, 2]]], [True, []]], ['one flipped face', [[[0, 2, 1], [0, 3, 1], [1, 2, 3], [0, 3, 2]]], [True, [1]]], ['mobius', [[[0, 3, 4, 1], [1, 4, 5, 2], [2, 5, 0, 3]]], [False, []]], ['projective plane', [[[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 5], [0, 5, 1], [1, 2, 4], [2, 3, 5], [3, 4, 1], [4, 5, 2], [5, 1, 3]]], [False, []]], ['book', [[[0, 1, 2], [1, 0, 3], [0, 1, 4]]], 'non-manifold'], ['quad grid', [[[0, 1, 4, 3], [1, 2, 5, 4], [3, 4, 7, 6], [4, 5, 8, 7]]], [True, []]], ['second component consistent', [[[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 5], [0, 5, 1], [10, 11, 12], [10, 11, 13]]], [True, [6]]]], [['one flipped face', [[[0, 2, 1], [0, 3, 1], [1, 2, 3], [0, 3, 2]]], [True, [1]]], ['mobius', [[[0, 3, 4, 1], [1, 4, 5, 2], [2, 5, 0, 3]]], [False, []]], ['projective plane', [[[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 5], [0, 5, 1], [1, 2, 4], [2, 3, 5], [3, 4, 1], [4, 5, 2], [5, 1, 3]]], [False, []]], ['book', [[[0, 1, 2], [1, 0, 3], [0, 1, 4]]], 'non-manifold'], ['flipped pair', [[[0, 1, 2], [0, 1, 3]]], [True, [1]]], ['disk with two flips', [[[0, 1, 2], [0, 3, 2], [0, 3, 4], [0, 5, 4], [0, 5, 1]]], [True, [1, 3]]], ['two components second flipped', [[[0, 2, 1], [0, 1, 3], [1, 2, 3], [0, 3, 2], [4, 5, 6], [4, 5, 7]]], [True, [5]]]]]
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)

source:
"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(x):
    faces=x
    edge_faces={}
    for fi,f in enumerate(faces):
        n=len(f)
        for i in range(n):
            a,b=f[i],f[(i+1)%n]
            edge_faces.setdefault((min(a,b),max(a,b)),[]).append((fi,a,b))
    if any(len(v)>=2 for v in edge_faces.values()): return 'non-manifold'
    flip=[None]*len(faces)
    for seed in range(len(faces)):
        if flip[seed] is not None: continue
        flip[seed]=0
        queue=[seed]
        while queue:
            fi=queue.pop(0)
            f=faces[fi]
            n=len(f)
            for i in range(n):
                a,b=f[i],f[(i+1)%n]
                for gj,c,d in edge_faces[(min(a,b),max(a,b))]:
                    if gj==fi: continue
                    same=1 if (c,d)==(a,b) else 0
                    want=flip[fi]^same
                    if flip[gj] is None:
                        flip[gj]=want
                        queue.append(gj)
                    elif flip[gj]!=want:
                        return [False,[]]
    return [True,[i for i in range(len(faces)) if flip[i]]]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['consistent tetrahedron', [[[0, 2, 1], [0, 1, 3], [1, 2, 3], [0, 3, 2]]], [True, []]], ['one flipped face', [[[0, 2, 1], [0, 3, 1], [1, 2, 3], [0, 3, 2]]], [True, [1]]], ['mobius', [[[0, 3, 4, 1], [1, 4, 5, 2], [2, 5, 0, 3]]], [False, []]], ['projective plane', [[[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 5], [0, 5, 1], [1, 2, 4], [2, 3, 5], [3, 4, 1], [4, 5, 2], [5, 1, 3]]], [False, []]], ['book', [[[0, 1, 2], [1, 0, 3], [0, 1, 4]]], 'non-manifold'], ['flipped pair', [[[0, 1, 2], [0, 1, 3]]], [True, [1]]], ['disk with two flips', [[[0, 1, 2], [0, 3, 2], [0, 3, 4], [0, 5, 4], [0, 5, 1]]], [True, [1, 3]]]], [['one flipped face', [[[0, 2, 1], [0, 3, 1], [1, 2, 3], [0, 3, 2]]], [True, [1]]], ['book', [[[0, 1, 2], [1, 0, 3], [0, 1, 4]]], 'non-manifold'], ['flipped pair', [[[0, 1, 2], [0, 1, 3]]], [True, [1]]], ['disk with two flips', [[[0, 1, 2], [0, 3, 2], [0, 3, 4], [0, 5, 4], [0, 5, 1]]], [True, [1, 3]]], ['two components second flipped', [[[0, 2, 1], [0, 1, 3], [1, 2, 3], [0, 3, 2], [4, 5, 6], [4, 5, 7]]], [True, [5]]], ['cube one flipped', [[[0, 3, 2, 1], [4, 5, 6, 7], [0, 4, 5, 1], [1, 2, 6, 5], [2, 3, 7, 6], [3, 0, 4, 7]]], [True, [2]]], ['annulus', [[[0, 3, 4, 1], [1, 4, 5, 2], [2, 5, 3, 0]]], [True, []]]], [['mobius', [[[0, 3, 4, 1], [1, 4, 5, 2], [2, 5, 0, 3]]], [False, []]], ['book', [[[0, 1, 2], [1, 0, 3], [0, 1, 4]]], 'non-manifold'], ['cube one flipped', [[[0, 3, 2, 1], [4, 5, 6, 7], [0, 4, 5, 1], [1, 2, 6, 5], [2, 3, 7, 6], [3, 0, 4, 7]]], [True, [2]]], ['annulus', [[[0, 3, 4, 1], [1, 4, 5, 2], [2, 5, 3, 0]]], [True, []]], ['chain of flips', [[[0, 1, 2], [1, 2, 3], [2, 3, 4], [3, 4, 5]]], [True, [1, 3]]], ['quad grid', [[[0, 1, 4, 3], [1, 2, 5, 4], [3, 4, 7, 6], [4, 5, 8, 7]]], [True, []]], ['second component consistent', [[[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 5], [0, 5, 1], [10, 11, 12], [10, 11, 13]]], [True, [6]]]], [['consistent tetrahedron', [[[0, 2, 1], [0, 1, 3], [1, 2, 3], [0, 3, 2]]], [True, []]], ['one flipped face', [[[0, 2, 1], [0, 3, 1], [1, 2, 3], [0, 3, 2]]], [True, [1]]], ['mobius', [[[0, 3, 4, 1], [1, 4, 5, 2], [2, 5, 0, 3]]], [False, []]], ['projective plane', [[[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 5], [0, 5, 1], [1, 2, 4], [2, 3, 5], [3, 4, 1], [4, 5, 2], [5, 1, 3]]], [False, []]], ['book', [[[0, 1, 2], [1, 0, 3], [0, 1, 4]]], 'non-manifold'], ['quad grid', [[[0, 1, 4, 3], [1, 2, 5, 4], [3, 4, 7, 6], [4, 5, 8, 7]]], [True, []]], ['second component consistent', [[[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 5], [0, 5, 1], [10, 11, 12], [10, 11, 13]]], [True, [6]]]], [['one flipped face', [[[0, 2, 1], [0, 3, 1], [1, 2, 3], [0, 3, 2]]], [True, [1]]], ['mobius', [[[0, 3, 4, 1], [1, 4, 5, 2], [2, 5, 0, 3]]], [False, []]], ['projective plane', [[[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 5], [0, 5, 1], [1, 2, 4], [2, 3, 5], [3, 4, 1], [4, 5, 2], [5, 1, 3]]], [False, []]], ['book', [[[0, 1, 2], [1, 0, 3], [0, 1, 4]]], 'non-manifold'], ['flipped pair', [[[0, 1, 2], [0, 1, 3]]], [True, [1]]], ['disk with two flips', [[[0, 1, 2], [0, 3, 2], [0, 3, 4], [0, 5, 4], [0, 5, 1]]], [True, [1, 3]]], ['two components second flipped', [[[0, 2, 1], [0, 1, 3], [1, 2, 3], [0, 3, 2], [4, 5, 6], [4, 5, 7]]], [True, [5]]]]]
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)

prompt:
Non-manifold books get an orientability answer instead of "non-manifold".

Input: polygon faces. If any undirected edge has more than two incident faces return "non-manifold". Otherwise propagate orientation by breadth-first search from the lowest unvisited face of each component (that seed keeps its orientation). A neighbour across an edge used in the same direction must have the opposite flip state. Any conflict returns [false, []], else [true, sorted indices of faces to flip].

split: open-access


prompt:
Faces with repeated corners survive and keep otherwise unused vertices alive.

Input [verts, faces]: drop faces with fewer than 3 distinct vertices, then keep only vertices referenced by remaining faces, renumbered 0-based in increasing old-index order. Faces keep their corner order. Return [kept vertex payloads, remapped faces].

split: open-access


prompt:
Orphan vertices from discarded degenerate faces remain in the output.

Input [verts, faces]: drop faces with fewer than 3 distinct vertices, then keep only vertices referenced by remaining faces, renumbered 0-based in increasing old-index order. Faces keep their corner order. Return [kept vertex payloads, remapped faces].

split: open-access


prompt:
The output vertex order depends on face order instead of the original index order.

Input [verts, faces]: drop faces with fewer than 3 distinct vertices, then keep only vertices referenced by remaining faces, renumbered 0-based in increasing old-index order. Faces keep their corner order. Return [kept vertex payloads, remapped faces].

split: open-access


prompt:
Every remapped face points one vertex too far.

Input [verts, faces]: drop faces with fewer than 3 distinct vertices, then keep only vertices referenced by remaining faces, renumbered 0-based in increasing old-index order. Faces keep their corner order. Return [kept vertex payloads, remapped faces].

split: open-access


prompt:
Points just left of a cell centre on the negative side weld with the wrong neighbour.

Input [points, faces, eps]. Points weld when floor(c/eps+0.5) agrees on every coordinate; the welded vertex takes the next new id and is represented by its lowest original index. Remap faces, merge consecutive equal corners (also across the wrap), drop faces with fewer than 3 corners, rotate each face so its smallest id comes first (orientation kept) and drop later copies of an identical rotated face. Return [representatives, faces].

split: open-access


prompt:
The representative list points at the last merged point instead of the lowest index.

Input [points, faces, eps]. Points weld when floor(c/eps+0.5) agrees on every coordinate; the welded vertex takes the next new id and is represented by its lowest original index. Remap faces, merge consecutive equal corners (also across the wrap), drop faces with fewer than 3 corners, rotate each face so its smallest id comes first (orientation kept) and drop later copies of an identical rotated face. Return [representatives, faces].

split: open-access


prompt:
Polygons that legitimately revisit a vertex lose corners.

Input [points, faces, eps]. Points weld when floor(c/eps+0.5) agrees on every coordinate; the welded vertex takes the next new id and is represented by its lowest original index. Remap faces, merge consecutive equal corners (also across the wrap), drop faces with fewer than 3 corners, rotate each face so its smallest id comes first (orientation kept) and drop later copies of an identical rotated face. Return [representatives, faces].

split: open-access


prompt:
A face whose last corner welds onto its first keeps a zero-length closing edge.

Input [points, faces, eps]. Points weld when floor(c/eps+0.5) agrees on every coordinate; the welded vertex takes the next new id and is represented by its lowest original index. Remap faces, merge consecutive equal corners (also across the wrap), drop faces with fewer than 3 corners, rotate each face so its smallest id comes first (orientation kept) and drop later copies of an identical rotated face. Return [representatives, faces].

split: open-access


prompt:
The same face listed from a different start corner is kept twice.

Input [points, faces, eps]. Points weld when floor(c/eps+0.5) agrees on every coordinate; the welded vertex takes the next new id and is represented by its lowest original index. Remap faces, merge consecutive equal corners (also across the wrap), drop faces with fewer than 3 corners, rotate each face so its smallest id comes first (orientation kept) and drop later copies of an identical rotated face. Return [representatives, faces].

split: open-access


prompt:
Faces that weld down to one or two corners are kept.

Input [points, faces, eps]. Points weld when floor(c/eps+0.5) agrees on every coordinate; the welded vertex takes the next new id and is represented by its lowest original index. Remap faces, merge consecutive equal corners (also across the wrap), drop faces with fewer than 3 corners, rotate each face so its smallest id comes first (orientation kept) and drop later copies of an identical rotated face. Return [representatives, faces].

split: open-access


prompt:
Every generated triangle faces the opposite way from its polygon.

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].

split: open-access


prompt:
Quads become single triangles and polygons leave a hole.

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].

split: open-access


prompt:
Reported diagonals are one higher per polygon.

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].

split: open-access


prompt:
Invalid faces vanish instead of being reported.

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].

split: open-access


prompt:
Edge growth counts each shared triangle edge twice.

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].

split: open-access


prompt:
After a flip both new triangles face inward, breaking orientation consistency.

Input [faces, a, b] for oriented triangles. The flip needs a triangle holding half-edge a->b (apex c) and one holding b->a (apex d), else "boundary"; exactly two faces may contain both a and b, else "non-manifold"; c==d is "degenerate"; an existing undirected edge c-d is "edge-exists". Otherwise replace the first triangle in place by [c,a,d] and the second by [d,b,c] and return the face list.

split: open-access


prompt:
A flip that duplicates an edge already present elsewhere is accepted.

Input [faces, a, b] for oriented triangles. The flip needs a triangle holding half-edge a->b (apex c) and one holding b->a (apex d), else "boundary"; exactly two faces may contain both a and b, else "non-manifold"; c==d is "degenerate"; an existing undirected edge c-d is "edge-exists". Otherwise replace the first triangle in place by [c,a,d] and the second by [d,b,c] and return the face list.

split: open-access


prompt:
A folded pair is flipped into triangles that repeat a vertex.

Input [faces, a, b] for oriented triangles. The flip needs a triangle holding half-edge a->b (apex c) and one holding b->a (apex d), else "boundary"; exactly two faces may contain both a and b, else "non-manifold"; c==d is "degenerate"; an existing undirected edge c-d is "edge-exists". Otherwise replace the first triangle in place by [c,a,d] and the second by [d,b,c] and return the face list.

split: open-access


prompt:
Face indices referenced elsewhere now point at the other triangle.

Input [faces, a, b] for oriented triangles. The flip needs a triangle holding half-edge a->b (apex c) and one holding b->a (apex d), else "boundary"; exactly two faces may contain both a and b, else "non-manifold"; c==d is "degenerate"; an existing undirected edge c-d is "edge-exists". Otherwise replace the first triangle in place by [c,a,d] and the second by [d,b,c] and return the face list.

split: open-access


prompt:
The second apex is an endpoint of the flipped edge, so valid flips are refused as "edge-exists".

Input [faces, a, b] for oriented triangles. The flip needs a triangle holding half-edge a->b (apex c) and one holding b->a (apex d), else "boundary"; exactly two faces may contain both a and b, else "non-manifold"; c==d is "degenerate"; an existing undirected edge c-d is "edge-exists". Otherwise replace the first triangle in place by [c,a,d] and the second by [d,b,c] and return the face list.

split: open-access


prompt:
Neighbour rings come out in reverse angular order.

Input [faces, v] with consistently oriented polygons. Each face containing v maps its next corner p to its previous corner q (counter-clockwise order around v). A repeated p is "nonmanifold"; no incident face is "isolated". If exactly one p has no predecessor the ring is a boundary fan starting there; more than one is "nonmanifold"; otherwise start at the smallest neighbour. Walk successors; a walk that does not visit every neighbour is "nonmanifold". Return [ring, "boundary"|"interior"].

split: open-access


prompt:
Boundary vertices whose smallest neighbour is not the fan start are reported non-manifold.

Input [faces, v] with consistently oriented polygons. Each face containing v maps its next corner p to its previous corner q (counter-clockwise order around v). A repeated p is "nonmanifold"; no incident face is "isolated". If exactly one p has no predecessor the ring is a boundary fan starting there; more than one is "nonmanifold"; otherwise start at the smallest neighbour. Walk successors; a walk that does not visit every neighbour is "nonmanifold". Return [ring, "boundary"|"interior"].

split: open-access


prompt:
Every boundary vertex is reported non-manifold.

Input [faces, v] with consistently oriented polygons. Each face containing v maps its next corner p to its previous corner q (counter-clockwise order around v). A repeated p is "nonmanifold"; no incident face is "isolated". If exactly one p has no predecessor the ring is a boundary fan starting there; more than one is "nonmanifold"; otherwise start at the smallest neighbour. Walk successors; a walk that does not visit every neighbour is "nonmanifold". Return [ring, "boundary"|"interior"].

split: open-access


prompt:
Two faces leaving v along the same edge (a flipped neighbour) are merged into a plausible ring.

Input [faces, v] with consistently oriented polygons. Each face containing v maps its next corner p to its previous corner q (counter-clockwise order around v). A repeated p is "nonmanifold"; no incident face is "isolated". If exactly one p has no predecessor the ring is a boundary fan starting there; more than one is "nonmanifold"; otherwise start at the smallest neighbour. Walk successors; a walk that does not visit every neighbour is "nonmanifold". Return [ring, "boundary"|"interior"].

split: open-access


prompt:
Every ring collapses to its start vertex and is reported non-manifold.

Input [faces, v] with consistently oriented polygons. Each face containing v maps its next corner p to its previous corner q (counter-clockwise order around v). A repeated p is "nonmanifold"; no incident face is "isolated". If exactly one p has no predecessor the ring is a boundary fan starting there; more than one is "nonmanifold"; otherwise start at the smallest neighbour. Walk successors; a walk that does not visit every neighbour is "nonmanifold". Return [ring, "boundary"|"interior"].

split: open-access


broken_source:
"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(x):
    ops=x
    V=E=Fc=L=S=G=0
    D={'mvfs':(1,0,1,1,1,0),'kvfs':(-1,0,-1,-1,-1,0),'mev':(1,1,0,0,0,0),'kev':(-1,-1,0,0,0,0),
       'mef':(0,1,1,0,0,0),'kef':(0,-1,-1,-1,0,0),'kemr':(0,-1,0,1,0,0),'mekr':(0,1,0,-1,0,0),
       'kfmrh':(0,0,-1,0,0,1),'mfkrh':(0,0,1,0,0,-1)}
    for i,op in enumerate(ops):
        if op not in D: return ['unknown',i]
        d=D[op]
        V,E,Fc,L,S,G=V+d[0],E+d[1],Fc+d[2],L+d[3],S+d[4],G+d[5]
        if min(V,E,Fc,L,S,G)<0 or L<Fc: return ['invalid',i]
        if V-E+Fc-(L-Fc)!=2*(S-G): return ['broken-invariant',i]
    return [V,E,Fc,L,S,G]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['triangle lamina', [['mvfs', 'mev', 'mev', 'mef']], [3, 3, 2, 2, 1, 0]], ['tetrahedron', [['mvfs', 'mev', 'mev', 'mef', 'mev', 'mef', 'mef']], [4, 6, 4, 4, 1, 0]], ['square with hole ring', [['mvfs', 'mev', 'mev', 'mev', 'mef', 'mev', 'mev', 'mev', 'mef', 'kemr']], [7, 7, 3, 4, 1, 0]], ['torus handle', [['mvfs', 'mev', 'mev', 'mev', 'mef', 'mev', 'mev', 'mev', 'mef', 'kemr', 'kfmrh']], [7, 7, 2, 4, 1, 1]], ['undo handle', [['mvfs', 'mev', 'mev', 'mev', 'mef', 'mev', 'mev', 'mev', 'mef', 'kemr', 'kfmrh', 'mfkrh']], [7, 7, 3, 4, 1, 0]], ['ring then remake edge', [['mvfs', 'mev', 'mev', 'mef', 'mev', 'kemr', 'mekr']], [4, 4, 2, 2, 1, 0]], ['kill edge on empty', [['mvfs', 'kev']], ['invalid', 1]]], [['tetrahedron', [['mvfs', 'mev', 'mev', 'mef', 'mev', 'mef', 'mef']], [4, 6, 4, 4, 1, 0]], ['undo handle', [['mvfs', 'mev', 'mev', 'mev', 'mef', 'mev', 'mev', 'mev', 'mef', 'kemr', 'kfmrh', 'mfkrh']], [7, 7, 3, 4, 1, 0]], ['ring then remake edge', [['mvfs', 'mev', 'mev', 'mef', 'mev', 'kemr', 'mekr']], [4, 4, 2, 2, 1, 0]], ['kill edge on empty', [['mvfs', 'kev']], ['invalid', 1]], ['unknown op', [['mvfs', 'mev', 'split']], ['unknown', 2]], ['uppercase op', [['mvfs', 'MEV']], ['unknown', 1]], ['loop deficit', [['mvfs', 'mev', 'mekr']], ['invalid', 2]]], [['square with hole ring', [['mvfs', 'mev', 'mev', 'mev', 'mef', 'mev', 'mev', 'mev', 'mef', 'kemr']], [7, 7, 3, 4, 1, 0]], ['unknown op', [['mvfs', 'mev', 'split']], ['unknown', 2]], ['uppercase op', [['mvfs', 'MEV']], ['unknown', 1]], ['loop deficit', [['mvfs', 'mev', 'mekr']], ['invalid', 2]], ['two shells', [['mvfs', 'mev', 'mvfs', 'mev', 'mev', 'mef']], [5, 4, 3, 3, 2, 0]], ['face without loop', [['mvfs', 'mfkrh']], ['invalid', 1]], ['build and kill', [['mvfs', 'mev', 'mev', 'mef', 'kef', 'kev', 'kev', 'kvfs']], [0, 0, 0, 0, 0, 0]]], [['triangle lamina', [['mvfs', 'mev', 'mev', 'mef']], [3, 3, 2, 2, 1, 0]], ['tetrahedron', [['mvfs', 'mev', 'mev', 'mef', 'mev', 'mef', 'mef']], [4, 6, 4, 4, 1, 0]], ['torus handle', [['mvfs', 'mev', 'mev', 'mev', 'mef', 'mev', 'mev', 'mev', 'mef', 'kemr', 'kfmrh']], [7, 7, 2, 4, 1, 1]], ['two shells', [['mvfs', 'mev', 'mvfs', 'mev', 'mev', 'mef']], [5, 4, 3, 3, 2, 0]], ['face without loop', [['mvfs', 'mfkrh']], ['invalid', 1]], ['build and kill', [['mvfs', 'mev', 'mev', 'mef', 'kef', 'kev', 'kev', 'kvfs']], [0, 0, 0, 0, 0, 0]], ['hole into lamina', [['mvfs', 'mev', 'mev', 'mef', 'mev', 'mev', 'mev', 'mef', 'kemr', 'kfmrh', 'mev']], [7, 7, 2, 4, 1, 1]]], [['triangle lamina', [['mvfs', 'mev', 'mev', 'mef']], [3, 3, 2, 2, 1, 0]], ['tetrahedron', [['mvfs', 'mev', 'mev', 'mef', 'mev', 'mef', 'mef']], [4, 6, 4, 4, 1, 0]], ['square with hole ring', [['mvfs', 'mev', 'mev', 'mev', 'mef', 'mev', 'mev', 'mev', 'mef', 'kemr']], [7, 7, 3, 4, 1, 0]], ['torus handle', [['mvfs', 'mev', 'mev', 'mev', 'mef', 'mev', 'mev', 'mev', 'mef', 'kemr', 'kfmrh']], [7, 7, 2, 4, 1, 1]], ['undo handle', [['mvfs', 'mev', 'mev', 'mev', 'mef', 'mev', 'mev', 'mev', 'mef', 'kemr', 'kfmrh', 'mfkrh']], [7, 7, 3, 4, 1, 0]], ['ring then remake edge', [['mvfs', 'mev', 'mev', 'mef', 'mev', 'kemr', 'mekr']], [4, 4, 2, 2, 1, 0]], ['hole into lamina', [['mvfs', 'mev', 'mev', 'mef', 'mev', 'mev', 'mev', 'mef', 'kemr', 'kfmrh', 'mev']], [7, 7, 2, 4, 1, 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)

source:
"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(x):
    ops=x
    V=E=Fc=L=S=G=0
    D={'mvfs':(1,0,1,1,1,0),'kvfs':(-1,0,-1,-1,-1,0),'mev':(1,1,0,0,0,0),'kev':(-1,-1,0,0,0,0),
       'mef':(0,1,1,2,0,0),'kef':(0,-1,-1,-1,0,0),'kemr':(0,-1,0,1,0,0),'mekr':(0,1,0,-1,0,0),
       'kfmrh':(0,0,-1,0,0,1),'mfkrh':(0,0,1,0,0,-1)}
    for i,op in enumerate(ops):
        if op not in D: return ['unknown',i]
        d=D[op]
        V,E,Fc,L,S,G=V+d[0],E+d[1],Fc+d[2],L+d[3],S+d[4],G+d[5]
        if min(V,E,Fc,L,S,G)<0 or L<Fc: return ['invalid',i]
        if V-E+Fc-(L-Fc)!=2*(S-G): return ['broken-invariant',i]
    return [V,E,Fc,L,S,G]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['triangle lamina', [['mvfs', 'mev', 'mev', 'mef']], [3, 3, 2, 2, 1, 0]], ['tetrahedron', [['mvfs', 'mev', 'mev', 'mef', 'mev', 'mef', 'mef']], [4, 6, 4, 4, 1, 0]], ['square with hole ring', [['mvfs', 'mev', 'mev', 'mev', 'mef', 'mev', 'mev', 'mev', 'mef', 'kemr']], [7, 7, 3, 4, 1, 0]], ['torus handle', [['mvfs', 'mev', 'mev', 'mev', 'mef', 'mev', 'mev', 'mev', 'mef', 'kemr', 'kfmrh']], [7, 7, 2, 4, 1, 1]], ['undo handle', [['mvfs', 'mev', 'mev', 'mev', 'mef', 'mev', 'mev', 'mev', 'mef', 'kemr', 'kfmrh', 'mfkrh']], [7, 7, 3, 4, 1, 0]], ['ring then remake edge', [['mvfs', 'mev', 'mev', 'mef', 'mev', 'kemr', 'mekr']], [4, 4, 2, 2, 1, 0]], ['kill edge on empty', [['mvfs', 'kev']], ['invalid', 1]]], [['tetrahedron', [['mvfs', 'mev', 'mev', 'mef', 'mev', 'mef', 'mef']], [4, 6, 4, 4, 1, 0]], ['undo handle', [['mvfs', 'mev', 'mev', 'mev', 'mef', 'mev', 'mev', 'mev', 'mef', 'kemr', 'kfmrh', 'mfkrh']], [7, 7, 3, 4, 1, 0]], ['ring then remake edge', [['mvfs', 'mev', 'mev', 'mef', 'mev', 'kemr', 'mekr']], [4, 4, 2, 2, 1, 0]], ['kill edge on empty', [['mvfs', 'kev']], ['invalid', 1]], ['unknown op', [['mvfs', 'mev', 'split']], ['unknown', 2]], ['uppercase op', [['mvfs', 'MEV']], ['unknown', 1]], ['loop deficit', [['mvfs', 'mev', 'mekr']], ['invalid', 2]]], [['square with hole ring', [['mvfs', 'mev', 'mev', 'mev', 'mef', 'mev', 'mev', 'mev', 'mef', 'kemr']], [7, 7, 3, 4, 1, 0]], ['unknown op', [['mvfs', 'mev', 'split']], ['unknown', 2]], ['uppercase op', [['mvfs', 'MEV']], ['unknown', 1]], ['loop deficit', [['mvfs', 'mev', 'mekr']], ['invalid', 2]], ['two shells', [['mvfs', 'mev', 'mvfs', 'mev', 'mev', 'mef']], [5, 4, 3, 3, 2, 0]], ['face without loop', [['mvfs', 'mfkrh']], ['invalid', 1]], ['build and kill', [['mvfs', 'mev', 'mev', 'mef', 'kef', 'kev', 'kev', 'kvfs']], [0, 0, 0, 0, 0, 0]]], [['triangle lamina', [['mvfs', 'mev', 'mev', 'mef']], [3, 3, 2, 2, 1, 0]], ['tetrahedron', [['mvfs', 'mev', 'mev', 'mef', 'mev', 'mef', 'mef']], [4, 6, 4, 4, 1, 0]], ['torus handle', [['mvfs', 'mev', 'mev', 'mev', 'mef', 'mev', 'mev', 'mev', 'mef', 'kemr', 'kfmrh']], [7, 7, 2, 4, 1, 1]], ['two shells', [['mvfs', 'mev', 'mvfs', 'mev', 'mev', 'mef']], [5, 4, 3, 3, 2, 0]], ['face without loop', [['mvfs', 'mfkrh']], ['invalid', 1]], ['build and kill', [['mvfs', 'mev', 'mev', 'mef', 'kef', 'kev', 'kev', 'kvfs']], [0, 0, 0, 0, 0, 0]], ['hole into lamina', [['mvfs', 'mev', 'mev', 'mef', 'mev', 'mev', 'mev', 'mef', 'kemr', 'kfmrh', 'mev']], [7, 7, 2, 4, 1, 1]]], [['triangle lamina', [['mvfs', 'mev', 'mev', 'mef']], [3, 3, 2, 2, 1, 0]], ['tetrahedron', [['mvfs', 'mev', 'mev', 'mef', 'mev', 'mef', 'mef']], [4, 6, 4, 4, 1, 0]], ['square with hole ring', [['mvfs', 'mev', 'mev', 'mev', 'mef', 'mev', 'mev', 'mev', 'mef', 'kemr']], [7, 7, 3, 4, 1, 0]], ['torus handle', [['mvfs', 'mev', 'mev', 'mev', 'mef', 'mev', 'mev', 'mev', 'mef', 'kemr', 'kfmrh']], [7, 7, 2, 4, 1, 1]], ['undo handle', [['mvfs', 'mev', 'mev', 'mev', 'mef', 'mev', 'mev', 'mev', 'mef', 'kemr', 'kfmrh', 'mfkrh']], [7, 7, 3, 4, 1, 0]], ['ring then remake edge', [['mvfs', 'mev', 'mev', 'mef', 'mev', 'kemr', 'mekr']], [4, 4, 2, 2, 1, 0]], ['hole into lamina', [['mvfs', 'mev', 'mev', 'mef', 'mev', 'mev', 'mev', 'mef', 'kemr', 'kfmrh', 'mev']], [7, 7, 2, 4, 1, 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)

prompt:
Every face-closing operation reports a broken invariant or too few loops.

Input: list of Euler operator names applied to counts [V,E,F,L,S,G] starting at zero. Deltas: mvfs(+V,+F,+L,+S), mev(+V,+E), mef(+E,+F,+L), kemr(-E,+L), mekr(+E,-L), kfmrh(-F,+G) and their inverses kvfs, kev, kef, mfkrh. After each op: an unknown name returns ["unknown", i]; a negative count or fewer loops than faces returns ["invalid", i]; a violated Euler-Poincare relation V-E+F-(L-F)=2(S-G) returns ["broken-invariant", i]. Return the final counts.

split: open-access


broken_source:
"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(x):
    ops=x
    V=E=Fc=L=S=G=0
    D={'mvfs':(1,0,1,1,1,0),'kvfs':(-1,0,-1,-1,-1,0),'mev':(1,1,0,0,0,0),'kev':(-1,-1,0,0,0,0),
       'mef':(0,1,1,1,0,0),'kef':(0,-1,-1,-1,0,0),'kemr':(0,-1,0,-1,0,0),'mekr':(0,1,0,-1,0,0),
       'kfmrh':(0,0,-1,0,0,1),'mfkrh':(0,0,1,0,0,-1)}
    for i,op in enumerate(ops):
        if op not in D: return ['unknown',i]
        d=D[op]
        V,E,Fc,L,S,G=V+d[0],E+d[1],Fc+d[2],L+d[3],S+d[4],G+d[5]
        if min(V,E,Fc,L,S,G)<0 or L<Fc: return ['invalid',i]
        if V-E+Fc-(L-Fc)!=2*(S-G): return ['broken-invariant',i]
    return [V,E,Fc,L,S,G]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['triangle lamina', [['mvfs', 'mev', 'mev', 'mef']], [3, 3, 2, 2, 1, 0]], ['tetrahedron', [['mvfs', 'mev', 'mev', 'mef', 'mev', 'mef', 'mef']], [4, 6, 4, 4, 1, 0]], ['square with hole ring', [['mvfs', 'mev', 'mev', 'mev', 'mef', 'mev', 'mev', 'mev', 'mef', 'kemr']], [7, 7, 3, 4, 1, 0]], ['torus handle', [['mvfs', 'mev', 'mev', 'mev', 'mef', 'mev', 'mev', 'mev', 'mef', 'kemr', 'kfmrh']], [7, 7, 2, 4, 1, 1]], ['undo handle', [['mvfs', 'mev', 'mev', 'mev', 'mef', 'mev', 'mev', 'mev', 'mef', 'kemr', 'kfmrh', 'mfkrh']], [7, 7, 3, 4, 1, 0]], ['ring then remake edge', [['mvfs', 'mev', 'mev', 'mef', 'mev', 'kemr', 'mekr']], [4, 4, 2, 2, 1, 0]], ['kill edge on empty', [['mvfs', 'kev']], ['invalid', 1]]], [['torus handle', [['mvfs', 'mev', 'mev', 'mev', 'mef', 'mev', 'mev', 'mev', 'mef', 'kemr', 'kfmrh']], [7, 7, 2, 4, 1, 1]], ['undo handle', [['mvfs', 'mev', 'mev', 'mev', 'mef', 'mev', 'mev', 'mev', 'mef', 'kemr', 'kfmrh', 'mfkrh']], [7, 7, 3, 4, 1, 0]], ['ring then remake edge', [['mvfs', 'mev', 'mev', 'mef', 'mev', 'kemr', 'mekr']], [4, 4, 2, 2, 1, 0]], ['kill edge on empty', [['mvfs', 'kev']], ['invalid', 1]], ['unknown op', [['mvfs', 'mev', 'split']], ['unknown', 2]], ['uppercase op', [['mvfs', 'MEV']], ['unknown', 1]], ['loop deficit', [['mvfs', 'mev', 'mekr']], ['invalid', 2]]], [['undo handle', [['mvfs', 'mev', 'mev', 'mev', 'mef', 'mev', 'mev', 'mev', 'mef', 'kemr', 'kfmrh', 'mfkrh']], [7, 7, 3, 4, 1, 0]], ['unknown op', [['mvfs', 'mev', 'split']], ['unknown', 2]], ['uppercase op', [['mvfs', 'MEV']], ['unknown', 1]], ['loop deficit', [['mvfs', 'mev', 'mekr']], ['invalid', 2]], ['two shells', [['mvfs', 'mev', 'mvfs', 'mev', 'mev', 'mef']], [5, 4, 3, 3, 2, 0]], ['face without loop', [['mvfs', 'mfkrh']], ['invalid', 1]], ['build and kill', [['mvfs', 'mev', 'mev', 'mef', 'kef', 'kev', 'kev', 'kvfs']], [0, 0, 0, 0, 0, 0]]], [['triangle lamina', [['mvfs', 'mev', 'mev', 'mef']], [3, 3, 2, 2, 1, 0]], ['tetrahedron', [['mvfs', 'mev', 'mev', 'mef', 'mev', 'mef', 'mef']], [4, 6, 4, 4, 1, 0]], ['ring then remake edge', [['mvfs', 'mev', 'mev', 'mef', 'mev', 'kemr', 'mekr']], [4, 4, 2, 2, 1, 0]], ['two shells', [['mvfs', 'mev', 'mvfs', 'mev', 'mev', 'mef']], [5, 4, 3, 3, 2, 0]], ['face without loop', [['mvfs', 'mfkrh']], ['invalid', 1]], ['build and kill', [['mvfs', 'mev', 'mev', 'mef', 'kef', 'kev', 'kev', 'kvfs']], [0, 0, 0, 0, 0, 0]], ['hole into lamina', [['mvfs', 'mev', 'mev', 'mef', 'mev', 'mev', 'mev', 'mef', 'kemr', 'kfmrh', 'mev']], [7, 7, 2, 4, 1, 1]]], [['triangle lamina', [['mvfs', 'mev', 'mev', 'mef']], [3, 3, 2, 2, 1, 0]], ['tetrahedron', [['mvfs', 'mev', 'mev', 'mef', 'mev', 'mef', 'mef']], [4, 6, 4, 4, 1, 0]], ['square with hole ring', [['mvfs', 'mev', 'mev', 'mev', 'mef', 'mev', 'mev', 'mev', 'mef', 'kemr']], [7, 7, 3, 4, 1, 0]], ['torus handle', [['mvfs', 'mev', 'mev', 'mev', 'mef', 'mev', 'mev', 'mev', 'mef', 'kemr', 'kfmrh']], [7, 7, 2, 4, 1, 1]], ['undo handle', [['mvfs', 'mev', 'mev', 'mev', 'mef', 'mev', 'mev', 'mev', 'mef', 'kemr', 'kfmrh', 'mfkrh']], [7, 7, 3, 4, 1, 0]], ['build and kill', [['mvfs', 'mev', 'mev', 'mef', 'kef', 'kev', 'kev', 'kvfs']], [0, 0, 0, 0, 0, 0]], ['hole into lamina', [['mvfs', 'mev', 'mev', 'mef', 'mev', 'mev', 'mev', 'mef', 'kemr', 'kfmrh', 'mev']], [7, 7, 2, 4, 1, 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)

source:
"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(x):
    ops=x
    V=E=Fc=L=S=G=0
    D={'mvfs':(1,0,1,1,1,0),'kvfs':(-1,0,-1,-1,-1,0),'mev':(1,1,0,0,0,0),'kev':(-1,-1,0,0,0,0),
       'mef':(0,1,1,1,0,0),'kef':(0,-1,-1,-1,0,0),'kemr':(0,1,0,1,0,0),'mekr':(0,1,0,-1,0,0),
       'kfmrh':(0,0,-1,0,0,1),'mfkrh':(0,0,1,0,0,-1)}
    for i,op in enumerate(ops):
        if op not in D: return ['unknown',i]
        d=D[op]
        V,E,Fc,L,S,G=V+d[0],E+d[1],Fc+d[2],L+d[3],S+d[4],G+d[5]
        if min(V,E,Fc,L,S,G)<0 or L<Fc: return ['invalid',i]
        if V-E+Fc-(L-Fc)!=2*(S-G): return ['broken-invariant',i]
    return [V,E,Fc,L,S,G]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['triangle lamina', [['mvfs', 'mev', 'mev', 'mef']], [3, 3, 2, 2, 1, 0]], ['tetrahedron', [['mvfs', 'mev', 'mev', 'mef', 'mev', 'mef', 'mef']], [4, 6, 4, 4, 1, 0]], ['square with hole ring', [['mvfs', 'mev', 'mev', 'mev', 'mef', 'mev', 'mev', 'mev', 'mef', 'kemr']], [7, 7, 3, 4, 1, 0]], ['torus handle', [['mvfs', 'mev', 'mev', 'mev', 'mef', 'mev', 'mev', 'mev', 'mef', 'kemr', 'kfmrh']], [7, 7, 2, 4, 1, 1]], ['undo handle', [['mvfs', 'mev', 'mev', 'mev', 'mef', 'mev', 'mev', 'mev', 'mef', 'kemr', 'kfmrh', 'mfkrh']], [7, 7, 3, 4, 1, 0]], ['ring then remake edge', [['mvfs', 'mev', 'mev', 'mef', 'mev', 'kemr', 'mekr']], [4, 4, 2, 2, 1, 0]], ['kill edge on empty', [['mvfs', 'kev']], ['invalid', 1]]], [['torus handle', [['mvfs', 'mev', 'mev', 'mev', 'mef', 'mev', 'mev', 'mev', 'mef', 'kemr', 'kfmrh']], [7, 7, 2, 4, 1, 1]], ['undo handle', [['mvfs', 'mev', 'mev', 'mev', 'mef', 'mev', 'mev', 'mev', 'mef', 'kemr', 'kfmrh', 'mfkrh']], [7, 7, 3, 4, 1, 0]], ['ring then remake edge', [['mvfs', 'mev', 'mev', 'mef', 'mev', 'kemr', 'mekr']], [4, 4, 2, 2, 1, 0]], ['kill edge on empty', [['mvfs', 'kev']], ['invalid', 1]], ['unknown op', [['mvfs', 'mev', 'split']], ['unknown', 2]], ['uppercase op', [['mvfs', 'MEV']], ['unknown', 1]], ['loop deficit', [['mvfs', 'mev', 'mekr']], ['invalid', 2]]], [['undo handle', [['mvfs', 'mev', 'mev', 'mev', 'mef', 'mev', 'mev', 'mev', 'mef', 'kemr', 'kfmrh', 'mfkrh']], [7, 7, 3, 4, 1, 0]], ['unknown op', [['mvfs', 'mev', 'split']], ['unknown', 2]], ['uppercase op', [['mvfs', 'MEV']], ['unknown', 1]], ['loop deficit', [['mvfs', 'mev', 'mekr']], ['invalid', 2]], ['two shells', [['mvfs', 'mev', 'mvfs', 'mev', 'mev', 'mef']], [5, 4, 3, 3, 2, 0]], ['face without loop', [['mvfs', 'mfkrh']], ['invalid', 1]], ['build and kill', [['mvfs', 'mev', 'mev', 'mef', 'kef', 'kev', 'kev', 'kvfs']], [0, 0, 0, 0, 0, 0]]], [['triangle lamina', [['mvfs', 'mev', 'mev', 'mef']], [3, 3, 2, 2, 1, 0]], ['tetrahedron', [['mvfs', 'mev', 'mev', 'mef', 'mev', 'mef', 'mef']], [4, 6, 4, 4, 1, 0]], ['ring then remake edge', [['mvfs', 'mev', 'mev', 'mef', 'mev', 'kemr', 'mekr']], [4, 4, 2, 2, 1, 0]], ['two shells', [['mvfs', 'mev', 'mvfs', 'mev', 'mev', 'mef']], [5, 4, 3, 3, 2, 0]], ['face without loop', [['mvfs', 'mfkrh']], ['invalid', 1]], ['build and kill', [['mvfs', 'mev', 'mev', 'mef', 'kef', 'kev', 'kev', 'kvfs']], [0, 0, 0, 0, 0, 0]], ['hole into lamina', [['mvfs', 'mev', 'mev', 'mef', 'mev', 'mev', 'mev', 'mef', 'kemr', 'kfmrh', 'mev']], [7, 7, 2, 4, 1, 1]]], [['triangle lamina', [['mvfs', 'mev', 'mev', 'mef']], [3, 3, 2, 2, 1, 0]], ['tetrahedron', [['mvfs', 'mev', 'mev', 'mef', 'mev', 'mef', 'mef']], [4, 6, 4, 4, 1, 0]], ['square with hole ring', [['mvfs', 'mev', 'mev', 'mev', 'mef', 'mev', 'mev', 'mev', 'mef', 'kemr']], [7, 7, 3, 4, 1, 0]], ['torus handle', [['mvfs', 'mev', 'mev', 'mev', 'mef', 'mev', 'mev', 'mev', 'mef', 'kemr', 'kfmrh']], [7, 7, 2, 4, 1, 1]], ['undo handle', [['mvfs', 'mev', 'mev', 'mev', 'mef', 'mev', 'mev', 'mev', 'mef', 'kemr', 'kfmrh', 'mfkrh']], [7, 7, 3, 4, 1, 0]], ['build and kill', [['mvfs', 'mev', 'mev', 'mef', 'kef', 'kev', 'kev', 'kvfs']], [0, 0, 0, 0, 0, 0]], ['hole into lamina', [['mvfs', 'mev', 'mev', 'mef', 'mev', 'mev', 'mev', 'mef', 'kemr', 'kfmrh', 'mev']], [7, 7, 2, 4, 1, 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)

prompt:
Creating an inner ring breaks the Euler-Poincare relation.

Input: list of Euler operator names applied to counts [V,E,F,L,S,G] starting at zero. Deltas: mvfs(+V,+F,+L,+S), mev(+V,+E), mef(+E,+F,+L), kemr(-E,+L), mekr(+E,-L), kfmrh(-F,+G) and their inverses kvfs, kev, kef, mfkrh. After each op: an unknown name returns ["unknown", i]; a negative count or fewer loops than faces returns ["invalid", i]; a violated Euler-Poincare relation V-E+F-(L-F)=2(S-G) returns ["broken-invariant", i]. Return the final counts.

split: open-access