FAILURE MAP
← Case archive

FA-87736 / Collision detection broadphase / Open access

Hash buckets keep particles from previous frames · case 01

Particles pair with ghosts of where neighbours were last frame.

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

ROOT CAUSE

The stamp check and lazy reset are missing.

VERIFIED REPAIR

Reset a bucket on its first insert of the frame.

Unsuccessful approach: Resetting without updating the stamp clears the bucket on every insert and loses real neighbours.

Case contract

solve(frames, n): particle hash table of n buckets reused across frames without clearing; a bucket whose stamp is older than the frame is lazily reset on first insert. Cell = floor(x), floor(y); bucket = ((ix*73856093 mod 2^32) xor (iy*19349663 mod 2^32)) mod n. A particle pairs with earlier particles in the same bucket only if they share the exact cell. Per frame return [sorted [min,max] pairs, buckets stamped this frame].

Why this case matters

Broadphase stages decide which object pairs ever reach narrowphase; a wrong boundary, ordering or bookkeeping rule silently drops real contacts or floods the solver with false candidates.

1 / The failure

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(frames, n):
    table = [[-1, []] for _ in range(n)]
    result = []
    for f, pts in enumerate(frames):
        pairs = []
        for pid, x, y in pts:
            ix, iy = math.floor(x), math.floor(y)
            h = (((ix * 73856093) & 0xFFFFFFFF) ^ ((iy * 19349663) & 0xFFFFFFFF)) % n
            slot = table[h]
            for qid, qx, qy in slot[1]:
                if (qx, qy) == (ix, iy):
                    pairs.append([min(pid, qid), max(pid, qid)])
            slot[1].append((pid, ix, iy))
        result.append([sorted(pairs), sum(1 for s in table if s[0] == f)])
    return result
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[[[[[[15, -2.0, 1.0], [13, -3.0, 0.0]], [[3, -3.0, 1.0], [13, -2.5, -2.5], [7, -2.0, -1.0]], [[19, -2.0, 3.0], [7, -0.5, 3.0], [3, 0.0, -1.0]], [[8, 0.5, -3.0], [11, 3.0, -1.5]]], 5], [[[], 2], [[], 2], [[], 3], [[], 2]]], [[[[[19, 1.5, 0.5], [5, 1.5, -2.5], [1, 0.5, -0.5]], [[5, -2.5, 3.0], [12, -2.5, -2.5], [13, -3.0, -0.5]], [[12, -2.0, 0.0], [15, 1.5, 2.0], [18, -2.5, -2.0], [14, -3.0, -3.0]], [[18, 1.5, -2.0], [2, 1.5, 1.0], [12, -1.0, -2.5]]], 11], [[[], 3], [[], 3], [[], 4], [[], 2]]], [[[[[12, -3.0, -0.5], [17, 0.5, 0.0], [3, 1.0, 0.5], [15, 3.0, -0.5], [16, 2.5, 2.5]], [[13, 2.0, -2.0], [11, 0.5, -2.5]]], 11], [[[], 4], [[], 2]]], [[[[[12, -2.5, 1.5], [8, 1.0, -2.5]], [[2, -1.0, 1.0], [3, -2.0, -1.0]]], 11], [[[], 2], [[], 2]]], [[[[[5, 2.0, 0.0], [14, 0.5, 0.5], [17, -1.0, 2.5], [4, 0.5, -2.0], [3, 1.5, 1.0]], [[11, -2.5, -0.5], [7, 2.5, 0.0], [16, 1.0, 2.5], [10, 1.0, -1.5]], [[9, -1.0, 2.0], [13, 1.0, 0.0]], [[19, -3.0, 2.0], [4, -3.0, 2.5], [18, 1.0, -3.0], [11, 0.0, 0.5], [9, 3.0, 0.0], [12, -3.0, 2.5]]], 11], [[[], 4], [[], 3], [[], 2], [[[4, 12], [4, 19], [12, 19]], 4]]], [[[[[19, -1.5, 1.5], [5, -3.0, 0.0], [7, -2.0, -1.0], [11, 0.0, 0.5], [1, 1.0, 1.5]], [[10, -1.5, -2.5], [4, -2.0, 1.0]], [[2, 0.5, 1.0], [12, 2.5, 3.0], [16, -0.5, -3.0]], [[13, -1.0, -0.5], [17, 0.0, -2.0], [18, 2.0, -2.0], [9, 2.0, 2.0], [1, 2.5, -1.5], [4, -1.0, -1.0]]], 7], [[[], 4], [[], 2], [[], 3], [[[1, 18], [4, 13]], 4]]], [[[[[9, -1.0, -3.0], [13, 2.5, -3.0], [17, -0.5, 0.5], [3, -0.5, -1.0], [14, 3.0, 0.0], [7, 2.0, -2.0]], [[7, 1.0, 3.0], [14, 1.0, -2.5], [13, -0.5, 0.0]], [[3, 0.5, -1.0], [10, 3.0, 0.5], [8, -2.0, 0.5]], [[19, 1.5, -1.0], [15, -1.0, -1.5], [13, -2.0, -0.5]]], 3], [[[], 3], [[], 2], [[], 2], [[], 2]]], [[[[[5, 3.0, 3.0], [4, -1.0, 3.0], [16, 2.5, 2.0]], [[17, 0.0, 1.0], [10, 1.5, 1.5]], [[16, 0.5, 0.0], [7, 2.0, -1.0], [2, -2.5, 1.0]], [[6, -1.0, -3.0], [1, -1.5, -0.5]]], 11], [[[], 2], [[], 2], [[], 2], [[], 2]]]], [[[[[[6, -0.5, 0.0], [8, 2.5, 0.0], [10, -2.0, 1.0], [16, 2.5, 2.5], [11, 0.0, 0.0], [13, -1.0, -2.0]], [[3, -0.5, 1.5], [5, 2.5, 1.0]]], 3], [[[], 3], [[], 2]]], [[[[[6, 3.0, 1.0], [15, 3.0, 1.0], [8, 0.5, 2.0], [5, 2.5, 0.0]]], 3], [[[[6, 15]], 2]]], [[[[[1, 0.5, 1.0], [2, 1.5, 0.0], [6, 3.0, 1.0], [3, 2.5, 2.5], [12, -1.0, -2.0]], [[2, 0.5, -2.0], [5, 2.5, -1.5]], [[11, -3.0, 3.0], [1, 0.0, 1.5], [7, 1.0, 2.5], [15, -2.0, 2.5], [2, -1.5, 3.0], [4, 2.5, 2.0]]], 11], [[[], 3], [[], 2], [[], 4]]], [[[[[3, -3.0, -0.5], [16, 0.5, 2.5], [4, 2.0, -1.0]], [[4, -3.0, 0.0], [16, 0.0, -1.5]]], 5], [[[], 3], [[], 2]]], [[[[[1, 2.0, -1.0], [2, -3.0, 1.5], [18, -3.0, 2.5], [8, 0.5, -1.5]], [[9, -1.5, -2.5], [17, -3.0, 2.5]], [[18, 1.0, 2.5], [6, 0.5, -2.0], [19, 1.0, -1.0]]], 3], [[[], 3], [[], 1], [[], 3]]], [[[[[3, -3.0, 2.5], [16, -1.5, -1.0]]], 3], [[[], 2]]], [[[[[2, -1.0, 0.0], [9, 2.0, 2.5], [15, 2.5, 0.0], [19, -3.0, 0.0], [18, 0.0, 1.0], [1, -2.5, -1.0]], [[17, -2.5, 2.5], [16, -3.0, -2.0], [8, 2.0, 2.5], [1, 1.5, 1.0], [18, 3.0, 1.5], [5, -2.0, 0.0]], [[17, -2.5, 1.0], [13, -2.5, -0.5], [16, -1.0, 1.5], [6, -2.0, -3.0], [9, 1.5, -1.5]]], 11], [[[], 5], [[], 5], [[], 3]]], [[[[[18, 0.5, 0.5], [19, 2.5, -3.0], [14, 1.0, 0.5], [4, 0.5, 1.5], [3, -2.0, -0.5], [6, 0.0, -3.0]], [[16, 1.5, 0.5], [4, -2.0, 0.5], [17, 2.0, -3.0]], [[1, 3.0, 2.5], [9, -0.5, -0.5], [2, -0.5, 1.5], [5, 3.0, 0.0], [4, -0.5, -2.0], [19, -1.0, 0.0]]], 5], [[[], 3], [[], 3], [[], 3]]]], [[[[[[8, 2.5, -0.5], [16, 0.5, 1.5], [13, 3.0, -1.5], [6, 3.0, -2.0]], [[17, -1.0, 0.0], [10, 2.5, -2.5], [8, 3.0, 3.0], [12, -1.0, -3.0]]], 11], [[[[6, 13]], 3], [[], 4]]], [[[[[19, 2.5, 1.0], [16, -0.5, 0.0], [15, 1.0, 3.0], [6, 1.0, 1.5], [1, -3.0, 1.5]], [[15, -1.5, -1.0], [2, -2.5, 1.5], [1, -3.0, 1.0]], [[5, -2.0, -2.0], [12, 1.0, -2.5], [19, 1.5, 1.0], [9, 0.0, 2.0], [14, 2.0, -1.5]]], 11], [[[], 5], [[[1, 2]], 2], [[], 4]]], [[[[[19, -3.0, 2.5], [2, 1.5, 0.0], [11, 2.0, 0.0], [4, 3.0, 1.0], [3, 0.0, 0.5], [16, -2.5, 1.5]]], 7], [[[], 5]]], [[[[[19, 2.5, -2.5], [1, -2.5, 0.5], [10, 1.0, -1.0], [16, 3.0, 1.0], [6, -1.0, 2.5]]], 11], [[[], 4]]], [[[[[8, -1.5, 2.5], [16, 1.5, -2.5], [12, -1.5, -2.0], [4, 1.0, -1.0], [9, -3.0, 2.5], [2, -3.0, 3.0]]], 7], [[[], 5]]], [[[[[3, 2.0, -3.0], [17, -2.0, -2.0]], [[1, -1.0, -2.5], [9, -2.5, 0.0], [18, -1.5, 1.5], [4, 1.5, 2.5], [5, 0.0, -3.0]]], 3], [[[], 2], [[], 2]]], [[[[[13, -2.5, -2.5], [6, 1.0, 0.5], [15, 0.5, -2.5], [16, -0.5, -2.0]], [[18, 2.5, 1.0], [15, -0.5, 0.5], [10, 2.5, -1.5]], [[14, 3.0, -2.5], [3, -1.0, 2.0], [10, 2.0, 0.0]], [[1, 2.0, -0.5], [12, 2.5, 0.0], [5, 2.0, 0.0], [14, -2.5, 3.0]]], 7], [[[], 3], [[], 3], [[], 2], [[[5, 12]], 2]]], [[[[[11, 0.5, 3.0], [2, -2.0, 0.5]], [[12, 1.0, -1.5], [15, 2.0, 3.0], [18, -1.0, 2.0], [4, 1.0, -2.5]]], 11], [[[], 1], [[], 4]]]], [[[[[[12, -1.5, 0.0], [10, 1.5, -1.0], [5, 0.5, 0.5]], [[10, -3.0, -2.5], [11, 1.5, -2.5], [8, 2.0, 2.0], [1, 1.5, 1.5], [12, -2.0, -0.5]]], 5], [[[], 1], [[], 4]]], [[[[[7, -0.5, 0.0], [18, -2.5, 1.0]], [[13, -2.5, -1.0], [12, -1.0, 3.0], [3, -3.0, 2.0], [18, 1.5, 2.0], [17, 2.5, 3.0]], [[11, -3.0, -3.0], [6, -1.0, 3.0], [13, -2.5, -2.5]], [[16, 2.0, 2.5], [3, 3.0, 1.5], [7, 0.5, 3.0], [12, 2.5, -1.0], [15, 2.0, 1.5], [5, 0.0, 0.0]]], 11], [[[], 2], [[], 4], [[[11, 13]], 2], [[], 6]]], [[[[[6, -0.5, 2.0], [16, 1.0, -1.5], [17, -0.5, -3.0], [7, -2.5, -1.5], [19, 1.5, 2.5]], [[15, -1.0, 3.0], [10, 2.5, -2.0], [2, 0.0, 3.0], [11, 3.0, -1.0]]], 5], [[[], 3], [[], 3]]], [[[[[7, -0.5, 1.5], [16, 0.5, 2.0], [8, -2.5, 2.5], [3, -2.0, 0.5], [1, 2.5, -2.0]]], 11], [[[], 5]]], [[[[[2, 0.0, 1.5], [10, -1.5, 3.0]], [[17, 2.5, 0.0], [15, 0.0, 0.0], [14, 2.5, 0.0], [11, -3.0, 1.0]], [[3, 0.0, -1.0], [4, -2.0, 0.0], [16, -0.5, -1.5], [9, -2.5, 3.0], [1, 0.0, 2.0]], [[18, 0.0, -1.5], [4, 1.0, 0.0], [17, 1.5, 2.0], [13, -2.5, -3.0], [3, 3.0, 0.0]]], 5], [[[], 2], [[[14, 17]], 2], [[], 3], [[], 4]]], [[[[[19, -3.0, 3.0], [17, -2.0, 2.5], [3, 2.0, -2.0]], [[1, 2.5, -1.0], [8, -1.0, 2.0], [13, 2.5, 2.5], [11, 0.0, 3.0], [10, 0.0, 0.0], [19, -0.5, 1.0]], [[12, -1.5, -0.5], [13, -2.5, -2.5], [7, -1.0, 2.0]]], 5], [[[], 2], [[], 3], [[], 2]]], [[[[[14, -2.0, 1.0], [1, 0.5, 1.5], [13, -1.5, 0.5]], [[1, 3.0, -1.5], [19, 2.5, -3.0]], [[2, -1.0, -0.5], [10, 3.0, 2.0]]], 11], [[[], 3], [[], 2], [[], 2]]], [[[[[10, -1.0, -0.5], [14, -3.0, 3.0], [5, -2.0, 1.0], [4, -1.0, 1.0], [2, -2.0, -1.0]], [[6, 2.0, -3.0], [18, -3.0, -0.5], [13, -2.5, 0.0], [11, -2.5, 3.0], [1, 0.0, 1.5], [16, -2.5, -3.0]]], 11], [[[], 5], [[], 4]]]], [[[[[[12, 0.5, 0.0], [9, 0.5, -1.0], [15, 0.0, 2.5], [8, 2.0, -1.0], [2, 2.5, -3.0], [10, 3.0, -2.5]]], 11], [[[], 5]]], [[[[[8, 1.5, -2.5], [3, 3.0, -3.0], [1, -2.5, 2.0], [9, 2.0, 3.0], [12, -2.5, 1.0]], [[8, 0.5, -1.5], [12, 2.0, -0.5], [11, -0.5, 2.0], [18, 2.5, -2.5], [16, 3.0, 2.5]], [[16, -0.5, 2.0], [13, 2.5, 0.5], [19, -2.0, 2.0]], [[13, -2.0, 2.0], [4, -3.0, -1.5], [9, -0.5, 0.5], [11, -2.5, -1.5]]], 7], [[[], 4], [[], 3], [[], 2], [[[4, 11]], 3]]], [[[[[8, -3.0, 0.0], [18, 0.0, -0.5], [7, 0.0, 3.0], [11, 1.5, -1.5]]], 5], [[[], 4]]], [[[[[14, 0.0, 3.0], [5, 2.0, 3.0], [10, -1.0, 0.0], [8, 0.0, 1.5], [1, -2.0, 2.5], [15, 2.0, 1.0]], [[6, 2.0, -2.0], [15, -2.5, 1.5]], [[19, -2.0, 0.0], [4, -0.5, -1.0], [18, -2.5, -2.5]], [[6, 0.5, 0.0], [7, -0.5, 1.0], [8, -1.5, 2.5]]], 3], [[[], 3], [[], 2], [[], 1], [[], 2]]], [[[[[1, -2.0, -0.5], [13, -2.5, 1.5], [16, 0.5, -1.5], [9, -1.5, 3.0], [10, 0.5, 0.5]], [[15, -0.5, -3.0], [4, 2.5, 0.5], [12, 2.5, -0.5]], [[3, 1.0, 1.5], [11, 0.5, 0.5], [5, 1.5, -2.5], [19, -0.5, -0.5]], [[5, -0.5, 2.5], [17, 0.0, -1.5], [11, -2.0, -1.0], [12, -2.0, 1.5]]], 11], [[[], 4], [[], 3], [[], 3], [[], 4]]], [[[[[9, -2.5, 2.5], [4, 1.5, 1.0], [16, -2.5, 2.0], [3, -1.5, -0.5]], [[12, -0.5, -2.5], [16, 3.0, -2.5], [18, -3.0, 3.0], [15, 1.0, 0.5], [9, 2.5, 3.0]], [[6, -1.0, 3.0], [10, 0.5, 2.5], [1, 0.0, -0.5]], [[9, -0.5, 1.0], [4, -2.5, -3.0], [12, 3.0, 3.0]]], 11], [[[[9, 16]], 2], [[], 4], [[], 3], [[], 2]]], [[[[[13, 1.0, -0.5], [1, -2.0, 1.0], [2, 2.0, 0.5], [14, 2.0, 3.0]], [[1, 2.5, -0.5], [10, 3.0, 1.5], [18, 1.0, 0.5], [15, 0.5, -2.5], [8, 2.0, -0.5], [6, -2.0, 1.0]]], 3], [[[], 3], [[[1, 8]], 3]]], [[[[[10, 1.5, 3.0], [13, 2.0, -2.5], [18, -2.0, 3.0], [1, 0.5, -0.5], [9, 3.0, 0.0], [6, -2.0, 1.5]], [[7, 1.0, 1.0], [5, -0.5, 0.0], [14, 1.0, -1.5]]], 7], [[[], 4], [[], 3]]]]]
for i, (args, expected) in enumerate(fixtures[N-1]):
    check("case %d" % i, solve(*args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
Boundary fixtureActualExpectedOutcome
case 0[[[], 0], [[], 0], [[], 0], [[], 0]][[[], 2], [[], 2], [[], 3], [[], 2]]Failed
case 1[[[], 0], [[], 0], [[[12, 14]], 0], [[], 0]][[[], 3], [[], 3], [[], 4], [[], 2]]Failed
case 2[[[], 0], [[], 0]][[[], 4], [[], 2]]Failed
case 3[[[], 0], [[], 0]][[[], 2], [[], 2]]Failed
case 4[[[], 0], [[[5, 7]], 0], [[[9, 17]], 0], [[[4, 12], [4, 19], [11, 14], [12, 19]], 0]][[[], 4], [[], 3], [[], 2], [[[4, 12], [4, 19], [12, 19]], 4]]Failed
case 5[[[], 0], [[[4, 19]], 0], [[], 0], [[[1, 18], [4, 13]], 0]][[[], 4], [[], 2], [[], 3], [[[1, 18], [4, 13]], 4]]Failed
case 6[[[], 0], [[[13, 17]], 0], [[[10, 14]], 0], [[], 0]][[[], 3], [[], 2], [[], 2], [[], 2]]Failed
case 7[[[], 0], [[], 0], [[], 0], [[], 0]][[[], 2], [[], 2], [[], 2], [[], 2]]Failed

SHA-256 / 9d55d04f061601b0f62fb0c7a307c20858d6ddfe8b5999e635d685742588035a

2 / The unsuccessful fix

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(frames, n):
    table = [[-1, []] for _ in range(n)]
    result = []
    for f, pts in enumerate(frames):
        pairs = []
        for pid, x, y in pts:
            ix, iy = math.floor(x), math.floor(y)
            h = (((ix * 73856093) & 0xFFFFFFFF) ^ ((iy * 19349663) & 0xFFFFFFFF)) % n
            slot = table[h]
            if slot[0] != f:
                slot[1] = []
            for qid, qx, qy in slot[1]:
                if (qx, qy) == (ix, iy):
                    pairs.append([min(pid, qid), max(pid, qid)])
            slot[1].append((pid, ix, iy))
        result.append([sorted(pairs), sum(1 for s in table if s[0] == f)])
    return result
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[[[[[[15, -2.0, 1.0], [13, -3.0, 0.0]], [[3, -3.0, 1.0], [13, -2.5, -2.5], [7, -2.0, -1.0]], [[19, -2.0, 3.0], [7, -0.5, 3.0], [3, 0.0, -1.0]], [[8, 0.5, -3.0], [11, 3.0, -1.5]]], 5], [[[], 2], [[], 2], [[], 3], [[], 2]]], [[[[[19, 1.5, 0.5], [5, 1.5, -2.5], [1, 0.5, -0.5]], [[5, -2.5, 3.0], [12, -2.5, -2.5], [13, -3.0, -0.5]], [[12, -2.0, 0.0], [15, 1.5, 2.0], [18, -2.5, -2.0], [14, -3.0, -3.0]], [[18, 1.5, -2.0], [2, 1.5, 1.0], [12, -1.0, -2.5]]], 11], [[[], 3], [[], 3], [[], 4], [[], 2]]], [[[[[12, -3.0, -0.5], [17, 0.5, 0.0], [3, 1.0, 0.5], [15, 3.0, -0.5], [16, 2.5, 2.5]], [[13, 2.0, -2.0], [11, 0.5, -2.5]]], 11], [[[], 4], [[], 2]]], [[[[[12, -2.5, 1.5], [8, 1.0, -2.5]], [[2, -1.0, 1.0], [3, -2.0, -1.0]]], 11], [[[], 2], [[], 2]]], [[[[[5, 2.0, 0.0], [14, 0.5, 0.5], [17, -1.0, 2.5], [4, 0.5, -2.0], [3, 1.5, 1.0]], [[11, -2.5, -0.5], [7, 2.5, 0.0], [16, 1.0, 2.5], [10, 1.0, -1.5]], [[9, -1.0, 2.0], [13, 1.0, 0.0]], [[19, -3.0, 2.0], [4, -3.0, 2.5], [18, 1.0, -3.0], [11, 0.0, 0.5], [9, 3.0, 0.0], [12, -3.0, 2.5]]], 11], [[[], 4], [[], 3], [[], 2], [[[4, 12], [4, 19], [12, 19]], 4]]], [[[[[19, -1.5, 1.5], [5, -3.0, 0.0], [7, -2.0, -1.0], [11, 0.0, 0.5], [1, 1.0, 1.5]], [[10, -1.5, -2.5], [4, -2.0, 1.0]], [[2, 0.5, 1.0], [12, 2.5, 3.0], [16, -0.5, -3.0]], [[13, -1.0, -0.5], [17, 0.0, -2.0], [18, 2.0, -2.0], [9, 2.0, 2.0], [1, 2.5, -1.5], [4, -1.0, -1.0]]], 7], [[[], 4], [[], 2], [[], 3], [[[1, 18], [4, 13]], 4]]], [[[[[9, -1.0, -3.0], [13, 2.5, -3.0], [17, -0.5, 0.5], [3, -0.5, -1.0], [14, 3.0, 0.0], [7, 2.0, -2.0]], [[7, 1.0, 3.0], [14, 1.0, -2.5], [13, -0.5, 0.0]], [[3, 0.5, -1.0], [10, 3.0, 0.5], [8, -2.0, 0.5]], [[19, 1.5, -1.0], [15, -1.0, -1.5], [13, -2.0, -0.5]]], 3], [[[], 3], [[], 2], [[], 2], [[], 2]]], [[[[[5, 3.0, 3.0], [4, -1.0, 3.0], [16, 2.5, 2.0]], [[17, 0.0, 1.0], [10, 1.5, 1.5]], [[16, 0.5, 0.0], [7, 2.0, -1.0], [2, -2.5, 1.0]], [[6, -1.0, -3.0], [1, -1.5, -0.5]]], 11], [[[], 2], [[], 2], [[], 2], [[], 2]]]], [[[[[[6, -0.5, 0.0], [8, 2.5, 0.0], [10, -2.0, 1.0], [16, 2.5, 2.5], [11, 0.0, 0.0], [13, -1.0, -2.0]], [[3, -0.5, 1.5], [5, 2.5, 1.0]]], 3], [[[], 3], [[], 2]]], [[[[[6, 3.0, 1.0], [15, 3.0, 1.0], [8, 0.5, 2.0], [5, 2.5, 0.0]]], 3], [[[[6, 15]], 2]]], [[[[[1, 0.5, 1.0], [2, 1.5, 0.0], [6, 3.0, 1.0], [3, 2.5, 2.5], [12, -1.0, -2.0]], [[2, 0.5, -2.0], [5, 2.5, -1.5]], [[11, -3.0, 3.0], [1, 0.0, 1.5], [7, 1.0, 2.5], [15, -2.0, 2.5], [2, -1.5, 3.0], [4, 2.5, 2.0]]], 11], [[[], 3], [[], 2], [[], 4]]], [[[[[3, -3.0, -0.5], [16, 0.5, 2.5], [4, 2.0, -1.0]], [[4, -3.0, 0.0], [16, 0.0, -1.5]]], 5], [[[], 3], [[], 2]]], [[[[[1, 2.0, -1.0], [2, -3.0, 1.5], [18, -3.0, 2.5], [8, 0.5, -1.5]], [[9, -1.5, -2.5], [17, -3.0, 2.5]], [[18, 1.0, 2.5], [6, 0.5, -2.0], [19, 1.0, -1.0]]], 3], [[[], 3], [[], 1], [[], 3]]], [[[[[3, -3.0, 2.5], [16, -1.5, -1.0]]], 3], [[[], 2]]], [[[[[2, -1.0, 0.0], [9, 2.0, 2.5], [15, 2.5, 0.0], [19, -3.0, 0.0], [18, 0.0, 1.0], [1, -2.5, -1.0]], [[17, -2.5, 2.5], [16, -3.0, -2.0], [8, 2.0, 2.5], [1, 1.5, 1.0], [18, 3.0, 1.5], [5, -2.0, 0.0]], [[17, -2.5, 1.0], [13, -2.5, -0.5], [16, -1.0, 1.5], [6, -2.0, -3.0], [9, 1.5, -1.5]]], 11], [[[], 5], [[], 5], [[], 3]]], [[[[[18, 0.5, 0.5], [19, 2.5, -3.0], [14, 1.0, 0.5], [4, 0.5, 1.5], [3, -2.0, -0.5], [6, 0.0, -3.0]], [[16, 1.5, 0.5], [4, -2.0, 0.5], [17, 2.0, -3.0]], [[1, 3.0, 2.5], [9, -0.5, -0.5], [2, -0.5, 1.5], [5, 3.0, 0.0], [4, -0.5, -2.0], [19, -1.0, 0.0]]], 5], [[[], 3], [[], 3], [[], 3]]]], [[[[[[8, 2.5, -0.5], [16, 0.5, 1.5], [13, 3.0, -1.5], [6, 3.0, -2.0]], [[17, -1.0, 0.0], [10, 2.5, -2.5], [8, 3.0, 3.0], [12, -1.0, -3.0]]], 11], [[[[6, 13]], 3], [[], 4]]], [[[[[19, 2.5, 1.0], [16, -0.5, 0.0], [15, 1.0, 3.0], [6, 1.0, 1.5], [1, -3.0, 1.5]], [[15, -1.5, -1.0], [2, -2.5, 1.5], [1, -3.0, 1.0]], [[5, -2.0, -2.0], [12, 1.0, -2.5], [19, 1.5, 1.0], [9, 0.0, 2.0], [14, 2.0, -1.5]]], 11], [[[], 5], [[[1, 2]], 2], [[], 4]]], [[[[[19, -3.0, 2.5], [2, 1.5, 0.0], [11, 2.0, 0.0], [4, 3.0, 1.0], [3, 0.0, 0.5], [16, -2.5, 1.5]]], 7], [[[], 5]]], [[[[[19, 2.5, -2.5], [1, -2.5, 0.5], [10, 1.0, -1.0], [16, 3.0, 1.0], [6, -1.0, 2.5]]], 11], [[[], 4]]], [[[[[8, -1.5, 2.5], [16, 1.5, -2.5], [12, -1.5, -2.0], [4, 1.0, -1.0], [9, -3.0, 2.5], [2, -3.0, 3.0]]], 7], [[[], 5]]], [[[[[3, 2.0, -3.0], [17, -2.0, -2.0]], [[1, -1.0, -2.5], [9, -2.5, 0.0], [18, -1.5, 1.5], [4, 1.5, 2.5], [5, 0.0, -3.0]]], 3], [[[], 2], [[], 2]]], [[[[[13, -2.5, -2.5], [6, 1.0, 0.5], [15, 0.5, -2.5], [16, -0.5, -2.0]], [[18, 2.5, 1.0], [15, -0.5, 0.5], [10, 2.5, -1.5]], [[14, 3.0, -2.5], [3, -1.0, 2.0], [10, 2.0, 0.0]], [[1, 2.0, -0.5], [12, 2.5, 0.0], [5, 2.0, 0.0], [14, -2.5, 3.0]]], 7], [[[], 3], [[], 3], [[], 2], [[[5, 12]], 2]]], [[[[[11, 0.5, 3.0], [2, -2.0, 0.5]], [[12, 1.0, -1.5], [15, 2.0, 3.0], [18, -1.0, 2.0], [4, 1.0, -2.5]]], 11], [[[], 1], [[], 4]]]], [[[[[[12, -1.5, 0.0], [10, 1.5, -1.0], [5, 0.5, 0.5]], [[10, -3.0, -2.5], [11, 1.5, -2.5], [8, 2.0, 2.0], [1, 1.5, 1.5], [12, -2.0, -0.5]]], 5], [[[], 1], [[], 4]]], [[[[[7, -0.5, 0.0], [18, -2.5, 1.0]], [[13, -2.5, -1.0], [12, -1.0, 3.0], [3, -3.0, 2.0], [18, 1.5, 2.0], [17, 2.5, 3.0]], [[11, -3.0, -3.0], [6, -1.0, 3.0], [13, -2.5, -2.5]], [[16, 2.0, 2.5], [3, 3.0, 1.5], [7, 0.5, 3.0], [12, 2.5, -1.0], [15, 2.0, 1.5], [5, 0.0, 0.0]]], 11], [[[], 2], [[], 4], [[[11, 13]], 2], [[], 6]]], [[[[[6, -0.5, 2.0], [16, 1.0, -1.5], [17, -0.5, -3.0], [7, -2.5, -1.5], [19, 1.5, 2.5]], [[15, -1.0, 3.0], [10, 2.5, -2.0], [2, 0.0, 3.0], [11, 3.0, -1.0]]], 5], [[[], 3], [[], 3]]], [[[[[7, -0.5, 1.5], [16, 0.5, 2.0], [8, -2.5, 2.5], [3, -2.0, 0.5], [1, 2.5, -2.0]]], 11], [[[], 5]]], [[[[[2, 0.0, 1.5], [10, -1.5, 3.0]], [[17, 2.5, 0.0], [15, 0.0, 0.0], [14, 2.5, 0.0], [11, -3.0, 1.0]], [[3, 0.0, -1.0], [4, -2.0, 0.0], [16, -0.5, -1.5], [9, -2.5, 3.0], [1, 0.0, 2.0]], [[18, 0.0, -1.5], [4, 1.0, 0.0], [17, 1.5, 2.0], [13, -2.5, -3.0], [3, 3.0, 0.0]]], 5], [[[], 2], [[[14, 17]], 2], [[], 3], [[], 4]]], [[[[[19, -3.0, 3.0], [17, -2.0, 2.5], [3, 2.0, -2.0]], [[1, 2.5, -1.0], [8, -1.0, 2.0], [13, 2.5, 2.5], [11, 0.0, 3.0], [10, 0.0, 0.0], [19, -0.5, 1.0]], [[12, -1.5, -0.5], [13, -2.5, -2.5], [7, -1.0, 2.0]]], 5], [[[], 2], [[], 3], [[], 2]]], [[[[[14, -2.0, 1.0], [1, 0.5, 1.5], [13, -1.5, 0.5]], [[1, 3.0, -1.5], [19, 2.5, -3.0]], [[2, -1.0, -0.5], [10, 3.0, 2.0]]], 11], [[[], 3], [[], 2], [[], 2]]], [[[[[10, -1.0, -0.5], [14, -3.0, 3.0], [5, -2.0, 1.0], [4, -1.0, 1.0], [2, -2.0, -1.0]], [[6, 2.0, -3.0], [18, -3.0, -0.5], [13, -2.5, 0.0], [11, -2.5, 3.0], [1, 0.0, 1.5], [16, -2.5, -3.0]]], 11], [[[], 5], [[], 4]]]], [[[[[[12, 0.5, 0.0], [9, 0.5, -1.0], [15, 0.0, 2.5], [8, 2.0, -1.0], [2, 2.5, -3.0], [10, 3.0, -2.5]]], 11], [[[], 5]]], [[[[[8, 1.5, -2.5], [3, 3.0, -3.0], [1, -2.5, 2.0], [9, 2.0, 3.0], [12, -2.5, 1.0]], [[8, 0.5, -1.5], [12, 2.0, -0.5], [11, -0.5, 2.0], [18, 2.5, -2.5], [16, 3.0, 2.5]], [[16, -0.5, 2.0], [13, 2.5, 0.5], [19, -2.0, 2.0]], [[13, -2.0, 2.0], [4, -3.0, -1.5], [9, -0.5, 0.5], [11, -2.5, -1.5]]], 7], [[[], 4], [[], 3], [[], 2], [[[4, 11]], 3]]], [[[[[8, -3.0, 0.0], [18, 0.0, -0.5], [7, 0.0, 3.0], [11, 1.5, -1.5]]], 5], [[[], 4]]], [[[[[14, 0.0, 3.0], [5, 2.0, 3.0], [10, -1.0, 0.0], [8, 0.0, 1.5], [1, -2.0, 2.5], [15, 2.0, 1.0]], [[6, 2.0, -2.0], [15, -2.5, 1.5]], [[19, -2.0, 0.0], [4, -0.5, -1.0], [18, -2.5, -2.5]], [[6, 0.5, 0.0], [7, -0.5, 1.0], [8, -1.5, 2.5]]], 3], [[[], 3], [[], 2], [[], 1], [[], 2]]], [[[[[1, -2.0, -0.5], [13, -2.5, 1.5], [16, 0.5, -1.5], [9, -1.5, 3.0], [10, 0.5, 0.5]], [[15, -0.5, -3.0], [4, 2.5, 0.5], [12, 2.5, -0.5]], [[3, 1.0, 1.5], [11, 0.5, 0.5], [5, 1.5, -2.5], [19, -0.5, -0.5]], [[5, -0.5, 2.5], [17, 0.0, -1.5], [11, -2.0, -1.0], [12, -2.0, 1.5]]], 11], [[[], 4], [[], 3], [[], 3], [[], 4]]], [[[[[9, -2.5, 2.5], [4, 1.5, 1.0], [16, -2.5, 2.0], [3, -1.5, -0.5]], [[12, -0.5, -2.5], [16, 3.0, -2.5], [18, -3.0, 3.0], [15, 1.0, 0.5], [9, 2.5, 3.0]], [[6, -1.0, 3.0], [10, 0.5, 2.5], [1, 0.0, -0.5]], [[9, -0.5, 1.0], [4, -2.5, -3.0], [12, 3.0, 3.0]]], 11], [[[[9, 16]], 2], [[], 4], [[], 3], [[], 2]]], [[[[[13, 1.0, -0.5], [1, -2.0, 1.0], [2, 2.0, 0.5], [14, 2.0, 3.0]], [[1, 2.5, -0.5], [10, 3.0, 1.5], [18, 1.0, 0.5], [15, 0.5, -2.5], [8, 2.0, -0.5], [6, -2.0, 1.0]]], 3], [[[], 3], [[[1, 8]], 3]]], [[[[[10, 1.5, 3.0], [13, 2.0, -2.5], [18, -2.0, 3.0], [1, 0.5, -0.5], [9, 3.0, 0.0], [6, -2.0, 1.5]], [[7, 1.0, 1.0], [5, -0.5, 0.0], [14, 1.0, -1.5]]], 7], [[[], 4], [[], 3]]]]]
for i, (args, expected) in enumerate(fixtures[N-1]):
    check("case %d" % i, solve(*args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
Boundary fixtureActualExpectedOutcome
case 0[[[], 0], [[], 0], [[], 0], [[], 0]][[[], 2], [[], 2], [[], 3], [[], 2]]Failed
case 1[[[], 0], [[], 0], [[], 0], [[], 0]][[[], 3], [[], 3], [[], 4], [[], 2]]Failed
case 2[[[], 0], [[], 0]][[[], 4], [[], 2]]Failed
case 3[[[], 0], [[], 0]][[[], 2], [[], 2]]Failed
case 4[[[], 0], [[], 0], [[], 0], [[], 0]][[[], 4], [[], 3], [[], 2], [[[4, 12], [4, 19], [12, 19]], 4]]Failed
case 5[[[], 0], [[], 0], [[], 0], [[], 0]][[[], 4], [[], 2], [[], 3], [[[1, 18], [4, 13]], 4]]Failed
case 6[[[], 0], [[], 0], [[], 0], [[], 0]][[[], 3], [[], 2], [[], 2], [[], 2]]Failed
case 7[[[], 0], [[], 0], [[], 0], [[], 0]][[[], 2], [[], 2], [[], 2], [[], 2]]Failed

SHA-256 / 80df2e44da418dd147a0ed181a480eaf0dcfc4eb34af7199c8f884763611b5f2

3 / The verified repair

Exit 0
"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(frames, n):
    table = [[-1, []] for _ in range(n)]
    result = []
    for f, pts in enumerate(frames):
        pairs = []
        for pid, x, y in pts:
            ix, iy = math.floor(x), math.floor(y)
            h = (((ix * 73856093) & 0xFFFFFFFF) ^ ((iy * 19349663) & 0xFFFFFFFF)) % n
            slot = table[h]
            if slot[0] != f:
                slot[0] = f
                slot[1] = []
            for qid, qx, qy in slot[1]:
                if (qx, qy) == (ix, iy):
                    pairs.append([min(pid, qid), max(pid, qid)])
            slot[1].append((pid, ix, iy))
        result.append([sorted(pairs), sum(1 for s in table if s[0] == f)])
    return result
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[[[[[[15, -2.0, 1.0], [13, -3.0, 0.0]], [[3, -3.0, 1.0], [13, -2.5, -2.5], [7, -2.0, -1.0]], [[19, -2.0, 3.0], [7, -0.5, 3.0], [3, 0.0, -1.0]], [[8, 0.5, -3.0], [11, 3.0, -1.5]]], 5], [[[], 2], [[], 2], [[], 3], [[], 2]]], [[[[[19, 1.5, 0.5], [5, 1.5, -2.5], [1, 0.5, -0.5]], [[5, -2.5, 3.0], [12, -2.5, -2.5], [13, -3.0, -0.5]], [[12, -2.0, 0.0], [15, 1.5, 2.0], [18, -2.5, -2.0], [14, -3.0, -3.0]], [[18, 1.5, -2.0], [2, 1.5, 1.0], [12, -1.0, -2.5]]], 11], [[[], 3], [[], 3], [[], 4], [[], 2]]], [[[[[12, -3.0, -0.5], [17, 0.5, 0.0], [3, 1.0, 0.5], [15, 3.0, -0.5], [16, 2.5, 2.5]], [[13, 2.0, -2.0], [11, 0.5, -2.5]]], 11], [[[], 4], [[], 2]]], [[[[[12, -2.5, 1.5], [8, 1.0, -2.5]], [[2, -1.0, 1.0], [3, -2.0, -1.0]]], 11], [[[], 2], [[], 2]]], [[[[[5, 2.0, 0.0], [14, 0.5, 0.5], [17, -1.0, 2.5], [4, 0.5, -2.0], [3, 1.5, 1.0]], [[11, -2.5, -0.5], [7, 2.5, 0.0], [16, 1.0, 2.5], [10, 1.0, -1.5]], [[9, -1.0, 2.0], [13, 1.0, 0.0]], [[19, -3.0, 2.0], [4, -3.0, 2.5], [18, 1.0, -3.0], [11, 0.0, 0.5], [9, 3.0, 0.0], [12, -3.0, 2.5]]], 11], [[[], 4], [[], 3], [[], 2], [[[4, 12], [4, 19], [12, 19]], 4]]], [[[[[19, -1.5, 1.5], [5, -3.0, 0.0], [7, -2.0, -1.0], [11, 0.0, 0.5], [1, 1.0, 1.5]], [[10, -1.5, -2.5], [4, -2.0, 1.0]], [[2, 0.5, 1.0], [12, 2.5, 3.0], [16, -0.5, -3.0]], [[13, -1.0, -0.5], [17, 0.0, -2.0], [18, 2.0, -2.0], [9, 2.0, 2.0], [1, 2.5, -1.5], [4, -1.0, -1.0]]], 7], [[[], 4], [[], 2], [[], 3], [[[1, 18], [4, 13]], 4]]], [[[[[9, -1.0, -3.0], [13, 2.5, -3.0], [17, -0.5, 0.5], [3, -0.5, -1.0], [14, 3.0, 0.0], [7, 2.0, -2.0]], [[7, 1.0, 3.0], [14, 1.0, -2.5], [13, -0.5, 0.0]], [[3, 0.5, -1.0], [10, 3.0, 0.5], [8, -2.0, 0.5]], [[19, 1.5, -1.0], [15, -1.0, -1.5], [13, -2.0, -0.5]]], 3], [[[], 3], [[], 2], [[], 2], [[], 2]]], [[[[[5, 3.0, 3.0], [4, -1.0, 3.0], [16, 2.5, 2.0]], [[17, 0.0, 1.0], [10, 1.5, 1.5]], [[16, 0.5, 0.0], [7, 2.0, -1.0], [2, -2.5, 1.0]], [[6, -1.0, -3.0], [1, -1.5, -0.5]]], 11], [[[], 2], [[], 2], [[], 2], [[], 2]]]], [[[[[[6, -0.5, 0.0], [8, 2.5, 0.0], [10, -2.0, 1.0], [16, 2.5, 2.5], [11, 0.0, 0.0], [13, -1.0, -2.0]], [[3, -0.5, 1.5], [5, 2.5, 1.0]]], 3], [[[], 3], [[], 2]]], [[[[[6, 3.0, 1.0], [15, 3.0, 1.0], [8, 0.5, 2.0], [5, 2.5, 0.0]]], 3], [[[[6, 15]], 2]]], [[[[[1, 0.5, 1.0], [2, 1.5, 0.0], [6, 3.0, 1.0], [3, 2.5, 2.5], [12, -1.0, -2.0]], [[2, 0.5, -2.0], [5, 2.5, -1.5]], [[11, -3.0, 3.0], [1, 0.0, 1.5], [7, 1.0, 2.5], [15, -2.0, 2.5], [2, -1.5, 3.0], [4, 2.5, 2.0]]], 11], [[[], 3], [[], 2], [[], 4]]], [[[[[3, -3.0, -0.5], [16, 0.5, 2.5], [4, 2.0, -1.0]], [[4, -3.0, 0.0], [16, 0.0, -1.5]]], 5], [[[], 3], [[], 2]]], [[[[[1, 2.0, -1.0], [2, -3.0, 1.5], [18, -3.0, 2.5], [8, 0.5, -1.5]], [[9, -1.5, -2.5], [17, -3.0, 2.5]], [[18, 1.0, 2.5], [6, 0.5, -2.0], [19, 1.0, -1.0]]], 3], [[[], 3], [[], 1], [[], 3]]], [[[[[3, -3.0, 2.5], [16, -1.5, -1.0]]], 3], [[[], 2]]], [[[[[2, -1.0, 0.0], [9, 2.0, 2.5], [15, 2.5, 0.0], [19, -3.0, 0.0], [18, 0.0, 1.0], [1, -2.5, -1.0]], [[17, -2.5, 2.5], [16, -3.0, -2.0], [8, 2.0, 2.5], [1, 1.5, 1.0], [18, 3.0, 1.5], [5, -2.0, 0.0]], [[17, -2.5, 1.0], [13, -2.5, -0.5], [16, -1.0, 1.5], [6, -2.0, -3.0], [9, 1.5, -1.5]]], 11], [[[], 5], [[], 5], [[], 3]]], [[[[[18, 0.5, 0.5], [19, 2.5, -3.0], [14, 1.0, 0.5], [4, 0.5, 1.5], [3, -2.0, -0.5], [6, 0.0, -3.0]], [[16, 1.5, 0.5], [4, -2.0, 0.5], [17, 2.0, -3.0]], [[1, 3.0, 2.5], [9, -0.5, -0.5], [2, -0.5, 1.5], [5, 3.0, 0.0], [4, -0.5, -2.0], [19, -1.0, 0.0]]], 5], [[[], 3], [[], 3], [[], 3]]]], [[[[[[8, 2.5, -0.5], [16, 0.5, 1.5], [13, 3.0, -1.5], [6, 3.0, -2.0]], [[17, -1.0, 0.0], [10, 2.5, -2.5], [8, 3.0, 3.0], [12, -1.0, -3.0]]], 11], [[[[6, 13]], 3], [[], 4]]], [[[[[19, 2.5, 1.0], [16, -0.5, 0.0], [15, 1.0, 3.0], [6, 1.0, 1.5], [1, -3.0, 1.5]], [[15, -1.5, -1.0], [2, -2.5, 1.5], [1, -3.0, 1.0]], [[5, -2.0, -2.0], [12, 1.0, -2.5], [19, 1.5, 1.0], [9, 0.0, 2.0], [14, 2.0, -1.5]]], 11], [[[], 5], [[[1, 2]], 2], [[], 4]]], [[[[[19, -3.0, 2.5], [2, 1.5, 0.0], [11, 2.0, 0.0], [4, 3.0, 1.0], [3, 0.0, 0.5], [16, -2.5, 1.5]]], 7], [[[], 5]]], [[[[[19, 2.5, -2.5], [1, -2.5, 0.5], [10, 1.0, -1.0], [16, 3.0, 1.0], [6, -1.0, 2.5]]], 11], [[[], 4]]], [[[[[8, -1.5, 2.5], [16, 1.5, -2.5], [12, -1.5, -2.0], [4, 1.0, -1.0], [9, -3.0, 2.5], [2, -3.0, 3.0]]], 7], [[[], 5]]], [[[[[3, 2.0, -3.0], [17, -2.0, -2.0]], [[1, -1.0, -2.5], [9, -2.5, 0.0], [18, -1.5, 1.5], [4, 1.5, 2.5], [5, 0.0, -3.0]]], 3], [[[], 2], [[], 2]]], [[[[[13, -2.5, -2.5], [6, 1.0, 0.5], [15, 0.5, -2.5], [16, -0.5, -2.0]], [[18, 2.5, 1.0], [15, -0.5, 0.5], [10, 2.5, -1.5]], [[14, 3.0, -2.5], [3, -1.0, 2.0], [10, 2.0, 0.0]], [[1, 2.0, -0.5], [12, 2.5, 0.0], [5, 2.0, 0.0], [14, -2.5, 3.0]]], 7], [[[], 3], [[], 3], [[], 2], [[[5, 12]], 2]]], [[[[[11, 0.5, 3.0], [2, -2.0, 0.5]], [[12, 1.0, -1.5], [15, 2.0, 3.0], [18, -1.0, 2.0], [4, 1.0, -2.5]]], 11], [[[], 1], [[], 4]]]], [[[[[[12, -1.5, 0.0], [10, 1.5, -1.0], [5, 0.5, 0.5]], [[10, -3.0, -2.5], [11, 1.5, -2.5], [8, 2.0, 2.0], [1, 1.5, 1.5], [12, -2.0, -0.5]]], 5], [[[], 1], [[], 4]]], [[[[[7, -0.5, 0.0], [18, -2.5, 1.0]], [[13, -2.5, -1.0], [12, -1.0, 3.0], [3, -3.0, 2.0], [18, 1.5, 2.0], [17, 2.5, 3.0]], [[11, -3.0, -3.0], [6, -1.0, 3.0], [13, -2.5, -2.5]], [[16, 2.0, 2.5], [3, 3.0, 1.5], [7, 0.5, 3.0], [12, 2.5, -1.0], [15, 2.0, 1.5], [5, 0.0, 0.0]]], 11], [[[], 2], [[], 4], [[[11, 13]], 2], [[], 6]]], [[[[[6, -0.5, 2.0], [16, 1.0, -1.5], [17, -0.5, -3.0], [7, -2.5, -1.5], [19, 1.5, 2.5]], [[15, -1.0, 3.0], [10, 2.5, -2.0], [2, 0.0, 3.0], [11, 3.0, -1.0]]], 5], [[[], 3], [[], 3]]], [[[[[7, -0.5, 1.5], [16, 0.5, 2.0], [8, -2.5, 2.5], [3, -2.0, 0.5], [1, 2.5, -2.0]]], 11], [[[], 5]]], [[[[[2, 0.0, 1.5], [10, -1.5, 3.0]], [[17, 2.5, 0.0], [15, 0.0, 0.0], [14, 2.5, 0.0], [11, -3.0, 1.0]], [[3, 0.0, -1.0], [4, -2.0, 0.0], [16, -0.5, -1.5], [9, -2.5, 3.0], [1, 0.0, 2.0]], [[18, 0.0, -1.5], [4, 1.0, 0.0], [17, 1.5, 2.0], [13, -2.5, -3.0], [3, 3.0, 0.0]]], 5], [[[], 2], [[[14, 17]], 2], [[], 3], [[], 4]]], [[[[[19, -3.0, 3.0], [17, -2.0, 2.5], [3, 2.0, -2.0]], [[1, 2.5, -1.0], [8, -1.0, 2.0], [13, 2.5, 2.5], [11, 0.0, 3.0], [10, 0.0, 0.0], [19, -0.5, 1.0]], [[12, -1.5, -0.5], [13, -2.5, -2.5], [7, -1.0, 2.0]]], 5], [[[], 2], [[], 3], [[], 2]]], [[[[[14, -2.0, 1.0], [1, 0.5, 1.5], [13, -1.5, 0.5]], [[1, 3.0, -1.5], [19, 2.5, -3.0]], [[2, -1.0, -0.5], [10, 3.0, 2.0]]], 11], [[[], 3], [[], 2], [[], 2]]], [[[[[10, -1.0, -0.5], [14, -3.0, 3.0], [5, -2.0, 1.0], [4, -1.0, 1.0], [2, -2.0, -1.0]], [[6, 2.0, -3.0], [18, -3.0, -0.5], [13, -2.5, 0.0], [11, -2.5, 3.0], [1, 0.0, 1.5], [16, -2.5, -3.0]]], 11], [[[], 5], [[], 4]]]], [[[[[[12, 0.5, 0.0], [9, 0.5, -1.0], [15, 0.0, 2.5], [8, 2.0, -1.0], [2, 2.5, -3.0], [10, 3.0, -2.5]]], 11], [[[], 5]]], [[[[[8, 1.5, -2.5], [3, 3.0, -3.0], [1, -2.5, 2.0], [9, 2.0, 3.0], [12, -2.5, 1.0]], [[8, 0.5, -1.5], [12, 2.0, -0.5], [11, -0.5, 2.0], [18, 2.5, -2.5], [16, 3.0, 2.5]], [[16, -0.5, 2.0], [13, 2.5, 0.5], [19, -2.0, 2.0]], [[13, -2.0, 2.0], [4, -3.0, -1.5], [9, -0.5, 0.5], [11, -2.5, -1.5]]], 7], [[[], 4], [[], 3], [[], 2], [[[4, 11]], 3]]], [[[[[8, -3.0, 0.0], [18, 0.0, -0.5], [7, 0.0, 3.0], [11, 1.5, -1.5]]], 5], [[[], 4]]], [[[[[14, 0.0, 3.0], [5, 2.0, 3.0], [10, -1.0, 0.0], [8, 0.0, 1.5], [1, -2.0, 2.5], [15, 2.0, 1.0]], [[6, 2.0, -2.0], [15, -2.5, 1.5]], [[19, -2.0, 0.0], [4, -0.5, -1.0], [18, -2.5, -2.5]], [[6, 0.5, 0.0], [7, -0.5, 1.0], [8, -1.5, 2.5]]], 3], [[[], 3], [[], 2], [[], 1], [[], 2]]], [[[[[1, -2.0, -0.5], [13, -2.5, 1.5], [16, 0.5, -1.5], [9, -1.5, 3.0], [10, 0.5, 0.5]], [[15, -0.5, -3.0], [4, 2.5, 0.5], [12, 2.5, -0.5]], [[3, 1.0, 1.5], [11, 0.5, 0.5], [5, 1.5, -2.5], [19, -0.5, -0.5]], [[5, -0.5, 2.5], [17, 0.0, -1.5], [11, -2.0, -1.0], [12, -2.0, 1.5]]], 11], [[[], 4], [[], 3], [[], 3], [[], 4]]], [[[[[9, -2.5, 2.5], [4, 1.5, 1.0], [16, -2.5, 2.0], [3, -1.5, -0.5]], [[12, -0.5, -2.5], [16, 3.0, -2.5], [18, -3.0, 3.0], [15, 1.0, 0.5], [9, 2.5, 3.0]], [[6, -1.0, 3.0], [10, 0.5, 2.5], [1, 0.0, -0.5]], [[9, -0.5, 1.0], [4, -2.5, -3.0], [12, 3.0, 3.0]]], 11], [[[[9, 16]], 2], [[], 4], [[], 3], [[], 2]]], [[[[[13, 1.0, -0.5], [1, -2.0, 1.0], [2, 2.0, 0.5], [14, 2.0, 3.0]], [[1, 2.5, -0.5], [10, 3.0, 1.5], [18, 1.0, 0.5], [15, 0.5, -2.5], [8, 2.0, -0.5], [6, -2.0, 1.0]]], 3], [[[], 3], [[[1, 8]], 3]]], [[[[[10, 1.5, 3.0], [13, 2.0, -2.5], [18, -2.0, 3.0], [1, 0.5, -0.5], [9, 3.0, 0.0], [6, -2.0, 1.5]], [[7, 1.0, 1.0], [5, -0.5, 0.0], [14, 1.0, -1.5]]], 7], [[[], 4], [[], 3]]]]]
for i, (args, expected) in enumerate(fixtures[N-1]):
    check("case %d" % i, solve(*args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
Boundary fixtureActualExpectedOutcome
case 0[[[], 2], [[], 2], [[], 3], [[], 2]][[[], 2], [[], 2], [[], 3], [[], 2]]Passed
case 1[[[], 3], [[], 3], [[], 4], [[], 2]][[[], 3], [[], 3], [[], 4], [[], 2]]Passed
case 2[[[], 4], [[], 2]][[[], 4], [[], 2]]Passed
case 3[[[], 2], [[], 2]][[[], 2], [[], 2]]Passed
case 4[[[], 4], [[], 3], [[], 2], [[[4, 12], [4, 19], [12, 19]], 4]][[[], 4], [[], 3], [[], 2], [[[4, 12], [4, 19], [12, 19]], 4]]Passed
case 5[[[], 4], [[], 2], [[], 3], [[[1, 18], [4, 13]], 4]][[[], 4], [[], 2], [[], 3], [[[1, 18], [4, 13]], 4]]Passed
case 6[[[], 3], [[], 2], [[], 2], [[], 2]][[[], 3], [[], 2], [[], 2], [[], 2]]Passed
case 7[[[], 2], [[], 2], [[], 2], [[], 2]][[[], 2], [[], 2], [[], 2], [[], 2]]Passed

SHA-256 / e85a003ee65b8faddd8158b27cca3d48c51cc6644aa955db8c203e57b9ad201f

Verification & scope

A deterministic bounded teaching model with stipulated toy conventions; not a production physics engine or spatial index. This reproducer isolates one failure mechanism. Results cover the supplied fixtures. Variants within a family share a test contract and should remain grouped when constructing evaluation splits. Related mechanisms with a shared evaluation_group must also remain together; these controlled models are not independent production incidents.

Observations recorded using Python 3.12.14 at 2026-09-29T14:51:01.634849+00:00.

Case digest / c1fa9fcafa400a6d6e6b7a3065346c1b07d439608ee99b8c1a18e8ce75073524