FA-82271 / Poker hand evaluation / Open access
Wheel draws show zero outs · case 01
A-2-3-4 is reported as having no straight outs.
ROOT CAUSE
The ace is mirrored to rank 0 instead of 1, so the five-high window 1-5 never completes.
VERIFIED REPAIR
Mirror the ace to rank 1 when testing straight windows.
Unsuccessful approach: Mirroring the king instead of the ace invents low windows for king-holding hands.
Case contract
Input: {"cards": known hole and board cards (4 to 6, no straight yet), "dead": other seen cards}. Return how many unseen cards would give the player a five-card straight (ace plays high or low): for every rank that completes a straight, count its four cards minus those already seen in cards or dead.
Why this case matters
Out counts feed pot-odds displays and all-in equity shortcuts.
1 / The failure
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(x):
R='23456789TJQKA'
known=x['cards']+x.get('dead',[])
ranks={R.index(c[0])+2 for c in x['cards']}
def has(rs):
rs=set(rs)
if 14 in rs: rs.add(0)
return any(all(t-i in rs for i in range(5)) for t in range(5,15))
if has(ranks): return 0
outs=0
for r in range(2,15):
if has(ranks|{r}):
outs+=4-sum(1 for c in known if R.index(c[0])+2==r)
return outs
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('open ended', {'cards': ['8h', '9d', 'Tc', 'Js', '2h'], 'dead': []}, 8),
('gutshot', {'cards': ['8h', '9d', 'Jc', 'Qs', '2h'], 'dead': []}, 4),
('ace-low draw', {'cards': ['Ah', '2d', '3c', '4s', 'Kh'], 'dead': []}, 4),
('ace-high draw', {'cards': ['Ah', 'Kd', 'Qc', 'Js', '2h'], 'dead': []}, 4),
('open ended with dead', {'cards': ['8h', '9d', 'Tc', 'Js', '2h'], 'dead': ['7c', 'Qd', 'Qs']},
5),
('paired board seen out', {'cards': ['8h', '9d', 'Tc', 'Js', 'Qh'], 'dead': []}, 0),
('no draw', {'cards': ['2h', '7d', 'Tc', 'Ks', '4h'], 'dead': []}, 0),
('wheel gutshot with dead', {'cards': ['Ah', '2d', '4c', '5s', 'Jh'], 'dead': ['3h']}, 3)],
[('ace-low draw', {'cards': ['Ah', '2d', '3c', '4s', 'Kh'], 'dead': []}, 4),
('open ended with dead', {'cards': ['8h', '9d', 'Tc', 'Js', '2h'], 'dead': ['7c', 'Qd', 'Qs']},
5),
('paired board seen out', {'cards': ['8h', '9d', 'Tc', 'Js', 'Qh'], 'dead': []}, 0),
('no draw', {'cards': ['2h', '7d', 'Tc', 'Ks', '4h'], 'dead': []}, 0),
('double gutshot', {'cards': ['7h', '9d', 'Tc', 'Js', 'Kh', '2c'], 'dead': []}, 8),
('wheel gutshot with dead', {'cards': ['Ah', '2d', '4c', '5s', 'Jh'], 'dead': ['3h']}, 3),
('three to straight only', {'cards': ['8h', '9d', 'Tc', '2s', '3h'], 'dead': []}, 0),
('two dead copies of an out',
{'cards': ['8h', '9d', 'Tc', 'Js', '2h'], 'dead': ['7c', '7d', 'Qd']}, 5)],
[('open ended', {'cards': ['8h', '9d', 'Tc', 'Js', '2h'], 'dead': []}, 8),
('gutshot', {'cards': ['8h', '9d', 'Jc', 'Qs', '2h'], 'dead': []}, 4),
('ace-low draw', {'cards': ['Ah', '2d', '3c', '4s', 'Kh'], 'dead': []}, 4),
('double gutshot', {'cards': ['7h', '9d', 'Tc', 'Js', 'Kh', '2c'], 'dead': []}, 8),
('wheel gutshot with dead', {'cards': ['Ah', '2d', '4c', '5s', 'Jh'], 'dead': ['3h']}, 3),
('three to straight only', {'cards': ['8h', '9d', 'Tc', '2s', '3h'], 'dead': []}, 0),
('two dead copies of an out',
{'cards': ['8h', '9d', 'Tc', 'Js', '2h'], 'dead': ['7c', '7d', 'Qd']}, 5),
('open ender with seen nine', {'cards': ['5h', '6d', '7c', '8s', '8h'], 'dead': ['9c', '4d']},
6)],
[('open ended', {'cards': ['8h', '9d', 'Tc', 'Js', '2h'], 'dead': []}, 8),
('gutshot', {'cards': ['8h', '9d', 'Jc', 'Qs', '2h'], 'dead': []}, 4),
('ace-low draw', {'cards': ['Ah', '2d', '3c', '4s', 'Kh'], 'dead': []}, 4),
('ace-high draw', {'cards': ['Ah', 'Kd', 'Qc', 'Js', '2h'], 'dead': []}, 4),
('open ended with dead', {'cards': ['8h', '9d', 'Tc', 'Js', '2h'], 'dead': ['7c', 'Qd', 'Qs']},
5),
('paired board seen out', {'cards': ['8h', '9d', 'Tc', 'Js', 'Qh'], 'dead': []}, 0),
('wheel gutshot with dead', {'cards': ['Ah', '2d', '4c', '5s', 'Jh'], 'dead': ['3h']}, 3),
('open ender with seen nine', {'cards': ['5h', '6d', '7c', '8s', '8h'], 'dead': ['9c', '4d']},
6)],
[('open ended', {'cards': ['8h', '9d', 'Tc', 'Js', '2h'], 'dead': []}, 8),
('gutshot', {'cards': ['8h', '9d', 'Jc', 'Qs', '2h'], 'dead': []}, 4),
('ace-low draw', {'cards': ['Ah', '2d', '3c', '4s', 'Kh'], 'dead': []}, 4),
('ace-high draw', {'cards': ['Ah', 'Kd', 'Qc', 'Js', '2h'], 'dead': []}, 4),
('open ended with dead', {'cards': ['8h', '9d', 'Tc', 'Js', '2h'], 'dead': ['7c', 'Qd', 'Qs']},
5),
('paired board seen out', {'cards': ['8h', '9d', 'Tc', 'Js', 'Qh'], 'dead': []}, 0),
('no draw', {'cards': ['2h', '7d', 'Tc', 'Ks', '4h'], 'dead': []}, 0),
('wheel gutshot with dead', {'cards': ['Ah', '2d', '4c', '5s', 'Jh'], 'dead': ['3h']}, 3)]]
for label, args, expected in fixtures[N-1]:
try:
actual = solve(args)
except Exception as exc:
actual = 'error:' + type(exc).__name__
check(label, actual, expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
| Boundary fixture | Actual | Expected | Outcome |
|---|---|---|---|
| open ended | 8 | 8 | Passed |
| gutshot | 4 | 4 | Passed |
| ace-low draw | 0 | 4 | Failed |
| ace-high draw | 4 | 4 | Passed |
| open ended with dead | 5 | 5 | Passed |
| paired board seen out | 0 | 0 | Passed |
| no draw | 0 | 0 | Passed |
| wheel gutshot with dead | 0 | 3 | Failed |
SHA-256 / fc30f42ccc26d1859a3be6dc5f04fa29d6d7fa84a27c10defa869df8667839bb
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(x):
R='23456789TJQKA'
known=x['cards']+x.get('dead',[])
ranks={R.index(c[0])+2 for c in x['cards']}
def has(rs):
rs=set(rs)
if 13 in rs: rs.add(1)
return any(all(t-i in rs for i in range(5)) for t in range(5,15))
if has(ranks): return 0
outs=0
for r in range(2,15):
if has(ranks|{r}):
outs+=4-sum(1 for c in known if R.index(c[0])+2==r)
return outs
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('open ended', {'cards': ['8h', '9d', 'Tc', 'Js', '2h'], 'dead': []}, 8),
('gutshot', {'cards': ['8h', '9d', 'Jc', 'Qs', '2h'], 'dead': []}, 4),
('ace-low draw', {'cards': ['Ah', '2d', '3c', '4s', 'Kh'], 'dead': []}, 4),
('ace-high draw', {'cards': ['Ah', 'Kd', 'Qc', 'Js', '2h'], 'dead': []}, 4),
('open ended with dead', {'cards': ['8h', '9d', 'Tc', 'Js', '2h'], 'dead': ['7c', 'Qd', 'Qs']},
5),
('paired board seen out', {'cards': ['8h', '9d', 'Tc', 'Js', 'Qh'], 'dead': []}, 0),
('no draw', {'cards': ['2h', '7d', 'Tc', 'Ks', '4h'], 'dead': []}, 0),
('wheel gutshot with dead', {'cards': ['Ah', '2d', '4c', '5s', 'Jh'], 'dead': ['3h']}, 3)],
[('ace-low draw', {'cards': ['Ah', '2d', '3c', '4s', 'Kh'], 'dead': []}, 4),
('open ended with dead', {'cards': ['8h', '9d', 'Tc', 'Js', '2h'], 'dead': ['7c', 'Qd', 'Qs']},
5),
('paired board seen out', {'cards': ['8h', '9d', 'Tc', 'Js', 'Qh'], 'dead': []}, 0),
('no draw', {'cards': ['2h', '7d', 'Tc', 'Ks', '4h'], 'dead': []}, 0),
('double gutshot', {'cards': ['7h', '9d', 'Tc', 'Js', 'Kh', '2c'], 'dead': []}, 8),
('wheel gutshot with dead', {'cards': ['Ah', '2d', '4c', '5s', 'Jh'], 'dead': ['3h']}, 3),
('three to straight only', {'cards': ['8h', '9d', 'Tc', '2s', '3h'], 'dead': []}, 0),
('two dead copies of an out',
{'cards': ['8h', '9d', 'Tc', 'Js', '2h'], 'dead': ['7c', '7d', 'Qd']}, 5)],
[('open ended', {'cards': ['8h', '9d', 'Tc', 'Js', '2h'], 'dead': []}, 8),
('gutshot', {'cards': ['8h', '9d', 'Jc', 'Qs', '2h'], 'dead': []}, 4),
('ace-low draw', {'cards': ['Ah', '2d', '3c', '4s', 'Kh'], 'dead': []}, 4),
('double gutshot', {'cards': ['7h', '9d', 'Tc', 'Js', 'Kh', '2c'], 'dead': []}, 8),
('wheel gutshot with dead', {'cards': ['Ah', '2d', '4c', '5s', 'Jh'], 'dead': ['3h']}, 3),
('three to straight only', {'cards': ['8h', '9d', 'Tc', '2s', '3h'], 'dead': []}, 0),
('two dead copies of an out',
{'cards': ['8h', '9d', 'Tc', 'Js', '2h'], 'dead': ['7c', '7d', 'Qd']}, 5),
('open ender with seen nine', {'cards': ['5h', '6d', '7c', '8s', '8h'], 'dead': ['9c', '4d']},
6)],
[('open ended', {'cards': ['8h', '9d', 'Tc', 'Js', '2h'], 'dead': []}, 8),
('gutshot', {'cards': ['8h', '9d', 'Jc', 'Qs', '2h'], 'dead': []}, 4),
('ace-low draw', {'cards': ['Ah', '2d', '3c', '4s', 'Kh'], 'dead': []}, 4),
('ace-high draw', {'cards': ['Ah', 'Kd', 'Qc', 'Js', '2h'], 'dead': []}, 4),
('open ended with dead', {'cards': ['8h', '9d', 'Tc', 'Js', '2h'], 'dead': ['7c', 'Qd', 'Qs']},
5),
('paired board seen out', {'cards': ['8h', '9d', 'Tc', 'Js', 'Qh'], 'dead': []}, 0),
('wheel gutshot with dead', {'cards': ['Ah', '2d', '4c', '5s', 'Jh'], 'dead': ['3h']}, 3),
('open ender with seen nine', {'cards': ['5h', '6d', '7c', '8s', '8h'], 'dead': ['9c', '4d']},
6)],
[('open ended', {'cards': ['8h', '9d', 'Tc', 'Js', '2h'], 'dead': []}, 8),
('gutshot', {'cards': ['8h', '9d', 'Jc', 'Qs', '2h'], 'dead': []}, 4),
('ace-low draw', {'cards': ['Ah', '2d', '3c', '4s', 'Kh'], 'dead': []}, 4),
('ace-high draw', {'cards': ['Ah', 'Kd', 'Qc', 'Js', '2h'], 'dead': []}, 4),
('open ended with dead', {'cards': ['8h', '9d', 'Tc', 'Js', '2h'], 'dead': ['7c', 'Qd', 'Qs']},
5),
('paired board seen out', {'cards': ['8h', '9d', 'Tc', 'Js', 'Qh'], 'dead': []}, 0),
('no draw', {'cards': ['2h', '7d', 'Tc', 'Ks', '4h'], 'dead': []}, 0),
('wheel gutshot with dead', {'cards': ['Ah', '2d', '4c', '5s', 'Jh'], 'dead': ['3h']}, 3)]]
for label, args, expected in fixtures[N-1]:
try:
actual = solve(args)
except Exception as exc:
actual = 'error:' + type(exc).__name__
check(label, actual, expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
| Boundary fixture | Actual | Expected | Outcome |
|---|---|---|---|
| open ended | 8 | 8 | Passed |
| gutshot | 4 | 4 | Passed |
| ace-low draw | 4 | 4 | Passed |
| ace-high draw | 4 | 4 | Passed |
| open ended with dead | 5 | 5 | Passed |
| paired board seen out | 0 | 0 | Passed |
| no draw | 0 | 0 | Passed |
| wheel gutshot with dead | 0 | 3 | Failed |
SHA-256 / b304a7b2fe5e391da6c8b0d1ad097607c2805fcdb3533c816b01e7e4f4b69216
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(x):
R='23456789TJQKA'
known=x['cards']+x.get('dead',[])
ranks={R.index(c[0])+2 for c in x['cards']}
def has(rs):
rs=set(rs)
if 14 in rs: rs.add(1)
return any(all(t-i in rs for i in range(5)) for t in range(5,15))
if has(ranks): return 0
outs=0
for r in range(2,15):
if has(ranks|{r}):
outs+=4-sum(1 for c in known if R.index(c[0])+2==r)
return outs
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('open ended', {'cards': ['8h', '9d', 'Tc', 'Js', '2h'], 'dead': []}, 8),
('gutshot', {'cards': ['8h', '9d', 'Jc', 'Qs', '2h'], 'dead': []}, 4),
('ace-low draw', {'cards': ['Ah', '2d', '3c', '4s', 'Kh'], 'dead': []}, 4),
('ace-high draw', {'cards': ['Ah', 'Kd', 'Qc', 'Js', '2h'], 'dead': []}, 4),
('open ended with dead', {'cards': ['8h', '9d', 'Tc', 'Js', '2h'], 'dead': ['7c', 'Qd', 'Qs']},
5),
('paired board seen out', {'cards': ['8h', '9d', 'Tc', 'Js', 'Qh'], 'dead': []}, 0),
('no draw', {'cards': ['2h', '7d', 'Tc', 'Ks', '4h'], 'dead': []}, 0),
('wheel gutshot with dead', {'cards': ['Ah', '2d', '4c', '5s', 'Jh'], 'dead': ['3h']}, 3)],
[('ace-low draw', {'cards': ['Ah', '2d', '3c', '4s', 'Kh'], 'dead': []}, 4),
('open ended with dead', {'cards': ['8h', '9d', 'Tc', 'Js', '2h'], 'dead': ['7c', 'Qd', 'Qs']},
5),
('paired board seen out', {'cards': ['8h', '9d', 'Tc', 'Js', 'Qh'], 'dead': []}, 0),
('no draw', {'cards': ['2h', '7d', 'Tc', 'Ks', '4h'], 'dead': []}, 0),
('double gutshot', {'cards': ['7h', '9d', 'Tc', 'Js', 'Kh', '2c'], 'dead': []}, 8),
('wheel gutshot with dead', {'cards': ['Ah', '2d', '4c', '5s', 'Jh'], 'dead': ['3h']}, 3),
('three to straight only', {'cards': ['8h', '9d', 'Tc', '2s', '3h'], 'dead': []}, 0),
('two dead copies of an out',
{'cards': ['8h', '9d', 'Tc', 'Js', '2h'], 'dead': ['7c', '7d', 'Qd']}, 5)],
[('open ended', {'cards': ['8h', '9d', 'Tc', 'Js', '2h'], 'dead': []}, 8),
('gutshot', {'cards': ['8h', '9d', 'Jc', 'Qs', '2h'], 'dead': []}, 4),
('ace-low draw', {'cards': ['Ah', '2d', '3c', '4s', 'Kh'], 'dead': []}, 4),
('double gutshot', {'cards': ['7h', '9d', 'Tc', 'Js', 'Kh', '2c'], 'dead': []}, 8),
('wheel gutshot with dead', {'cards': ['Ah', '2d', '4c', '5s', 'Jh'], 'dead': ['3h']}, 3),
('three to straight only', {'cards': ['8h', '9d', 'Tc', '2s', '3h'], 'dead': []}, 0),
('two dead copies of an out',
{'cards': ['8h', '9d', 'Tc', 'Js', '2h'], 'dead': ['7c', '7d', 'Qd']}, 5),
('open ender with seen nine', {'cards': ['5h', '6d', '7c', '8s', '8h'], 'dead': ['9c', '4d']},
6)],
[('open ended', {'cards': ['8h', '9d', 'Tc', 'Js', '2h'], 'dead': []}, 8),
('gutshot', {'cards': ['8h', '9d', 'Jc', 'Qs', '2h'], 'dead': []}, 4),
('ace-low draw', {'cards': ['Ah', '2d', '3c', '4s', 'Kh'], 'dead': []}, 4),
('ace-high draw', {'cards': ['Ah', 'Kd', 'Qc', 'Js', '2h'], 'dead': []}, 4),
('open ended with dead', {'cards': ['8h', '9d', 'Tc', 'Js', '2h'], 'dead': ['7c', 'Qd', 'Qs']},
5),
('paired board seen out', {'cards': ['8h', '9d', 'Tc', 'Js', 'Qh'], 'dead': []}, 0),
('wheel gutshot with dead', {'cards': ['Ah', '2d', '4c', '5s', 'Jh'], 'dead': ['3h']}, 3),
('open ender with seen nine', {'cards': ['5h', '6d', '7c', '8s', '8h'], 'dead': ['9c', '4d']},
6)],
[('open ended', {'cards': ['8h', '9d', 'Tc', 'Js', '2h'], 'dead': []}, 8),
('gutshot', {'cards': ['8h', '9d', 'Jc', 'Qs', '2h'], 'dead': []}, 4),
('ace-low draw', {'cards': ['Ah', '2d', '3c', '4s', 'Kh'], 'dead': []}, 4),
('ace-high draw', {'cards': ['Ah', 'Kd', 'Qc', 'Js', '2h'], 'dead': []}, 4),
('open ended with dead', {'cards': ['8h', '9d', 'Tc', 'Js', '2h'], 'dead': ['7c', 'Qd', 'Qs']},
5),
('paired board seen out', {'cards': ['8h', '9d', 'Tc', 'Js', 'Qh'], 'dead': []}, 0),
('no draw', {'cards': ['2h', '7d', 'Tc', 'Ks', '4h'], 'dead': []}, 0),
('wheel gutshot with dead', {'cards': ['Ah', '2d', '4c', '5s', 'Jh'], 'dead': ['3h']}, 3)]]
for label, args, expected in fixtures[N-1]:
try:
actual = solve(args)
except Exception as exc:
actual = 'error:' + type(exc).__name__
check(label, actual, expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
| Boundary fixture | Actual | Expected | Outcome |
|---|---|---|---|
| open ended | 8 | 8 | Passed |
| gutshot | 4 | 4 | Passed |
| ace-low draw | 4 | 4 | Passed |
| ace-high draw | 4 | 4 | Passed |
| open ended with dead | 5 | 5 | Passed |
| paired board seen out | 0 | 0 | Passed |
| no draw | 0 | 0 | Passed |
| wheel gutshot with dead | 3 | 3 | Passed |
SHA-256 / 6060cbf989dd65a431271a9ed735d699f4f2b49e072fdb8c9d26d0c396acc1d9
Verification & scope
A deterministic toy model with an explicitly stated contract; card strings are rank+suit (for example "As", "Td"); no claim of conformance to any casino or tournament rulebook. 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:50:10.699251+00:00.
Case digest / 5543e55ac1e0532439678fdb9211734c26ac9057a51ed0be63b87dbecaa10c26