FA-12796 / Tournament pairing rules / Open access
Greedy pairing strands the final entrants · case 01
Greedy pairing strands the final entrants.
ROOT CAUSE
A locally legal first opponent is committed before checking completion.
VERIFIED REPAIR
Distinct players are sorted ids; forbidden pairs are sorted lists. Return the first complete legal pairing in ascending opponent search order, or None.
Unsuccessful approach: Choosing the last opponent instead still lacks search and violates canonical ordering.
Case contract
Synthetic model: Distinct players are sorted ids; forbidden pairs are sorted lists. Return the first complete legal pairing in ascending opponent search order, or None.
Why this case matters
Makes the stated pairing or standings policy executable without assuming any real federation rulebook.
1 / The failure
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(players, forbidden):
remaining=list(players)
pairs=[]
while remaining:
a=remaining.pop(0)
choices=[b for b in remaining if sorted([a,b]) not in forbidden]
if not choices: return None
b=choices[0]; remaining.remove(b); pairs.append([a,b])
return pairs
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('greedy dead end', solve([N,N+1,N+2,N+3], [[N+2,N+3]]), [[N,N+2],[N+1,N+3]])
check('canonical matching', solve([N,N+1,N+2,N+3], []), [[N,N+1],[N+2,N+3]])
check('empty', solve([], []), [])
check('odd count', solve([N], []), None)
check('forbidden pair', solve([N,N+1], [[N,N+1]]), None)
check('single pair', solve([N,N+1], []), [[N,N+1]])
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
| Boundary fixture | Actual | Expected | Outcome |
|---|---|---|---|
| greedy dead end | None | [[1, 3], [2, 4]] | Failed |
| canonical matching | [[1, 2], [3, 4]] | [[1, 2], [3, 4]] | Passed |
| empty | [] | [] | Passed |
| odd count | None | None | Passed |
| forbidden pair | None | None | Passed |
| single pair | [[1, 2]] | [[1, 2]] | Passed |
SHA-256 / 1837fc65267b81fdc5d93deb586135349c6692f11d59aec3f1f9d287088666a9
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(players, forbidden):
remaining=list(players)
pairs=[]
while remaining:
a=remaining.pop(0)
choices=[b for b in remaining if sorted([a,b]) not in forbidden]
if not choices: return None
b=choices[-1]; remaining.remove(b); pairs.append([a,b])
return pairs
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('greedy dead end', solve([N,N+1,N+2,N+3], [[N+2,N+3]]), [[N,N+2],[N+1,N+3]])
check('canonical matching', solve([N,N+1,N+2,N+3], []), [[N,N+1],[N+2,N+3]])
check('empty', solve([], []), [])
check('odd count', solve([N], []), None)
check('forbidden pair', solve([N,N+1], [[N,N+1]]), None)
check('single pair', solve([N,N+1], []), [[N,N+1]])
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
| Boundary fixture | Actual | Expected | Outcome |
|---|---|---|---|
| greedy dead end | [[1, 4], [2, 3]] | [[1, 3], [2, 4]] | Failed |
| canonical matching | [[1, 4], [2, 3]] | [[1, 2], [3, 4]] | Failed |
| empty | [] | [] | Passed |
| odd count | None | None | Passed |
| forbidden pair | None | None | Passed |
| single pair | [[1, 2]] | [[1, 2]] | Passed |
SHA-256 / 0ac28665af17c92d643c4f3f255f25bb494716e9a9994b25287242584ae1b710
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(players, forbidden):
def search(rest):
if not rest: return []
a=rest[0]
for b in rest[1:]:
if sorted([a,b]) in forbidden: continue
tail=search([x for x in rest[1:] if x!=b])
if tail is not None: return [[a,b]]+tail
return None
return search(players)
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('greedy dead end', solve([N,N+1,N+2,N+3], [[N+2,N+3]]), [[N,N+2],[N+1,N+3]])
check('canonical matching', solve([N,N+1,N+2,N+3], []), [[N,N+1],[N+2,N+3]])
check('empty', solve([], []), [])
check('odd count', solve([N], []), None)
check('forbidden pair', solve([N,N+1], [[N,N+1]]), None)
check('single pair', solve([N,N+1], []), [[N,N+1]])
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
| Boundary fixture | Actual | Expected | Outcome |
|---|---|---|---|
| greedy dead end | [[1, 3], [2, 4]] | [[1, 3], [2, 4]] | Passed |
| canonical matching | [[1, 2], [3, 4]] | [[1, 2], [3, 4]] | Passed |
| empty | [] | [] | Passed |
| odd count | None | None | Passed |
| forbidden pair | None | None | Passed |
| single pair | [[1, 2]] | [[1, 2]] | Passed |
SHA-256 / de6f3e31aeb7c89154dc85e521560eef762225c27c0168b6013bd59032d4c59d
Verification & scope
Controlled synthetic policy; does not implement an entire tournament system. 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:39:00.127107+00:00.
Case digest / ae088fe13a1f703445814726cd32dcd8f8f45f844885ba6d7233785b2cde0f72