FA-82276 / Poker hand evaluation / Open access
Four-card run treated as a made straight · case 01
Open-ended draws report zero outs because the draw is already counted as a straight.
ROOT CAUSE
The straight window checks four consecutive ranks.
VERIFIED REPAIR
Require all five ranks of the window.
Unsuccessful approach: Accepting four of five window ranks is still a draw, not a straight.
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(1)
return any(all(t-i in rs for i in range(4)) 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),
('double gutshot', {'cards': ['7h', '9d', 'Tc', 'Js', 'Kh', '2c'], '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),
('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)],
[('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),
('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),
('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),
('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),
('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),
('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)]]
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 | 0 | 8 | Failed |
| gutshot | 4 | 4 | Passed |
| ace-low draw | 4 | 4 | Passed |
| ace-high draw | 0 | 4 | Failed |
| open ended with dead | 0 | 5 | Failed |
| paired board seen out | 0 | 0 | Passed |
| no draw | 0 | 0 | Passed |
| double gutshot | 8 | 8 | Passed |
SHA-256 / 7e143ace53b339bbeb7b0bc3a5dc4e08192fa2b900b640f59c0e73b00b16223d
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 14 in rs: rs.add(1)
return any(sum(t-i in rs for i in range(5))>=4 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),
('double gutshot', {'cards': ['7h', '9d', 'Tc', 'Js', 'Kh', '2c'], '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),
('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)],
[('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),
('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),
('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),
('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),
('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),
('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)]]
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 | 0 | 8 | Failed |
| gutshot | 0 | 4 | Failed |
| ace-low draw | 0 | 4 | Failed |
| ace-high draw | 0 | 4 | Failed |
| open ended with dead | 0 | 5 | Failed |
| paired board seen out | 0 | 0 | Passed |
| no draw | 0 | 0 | Passed |
| double gutshot | 0 | 8 | Failed |
SHA-256 / b70b7c4eb75e0f190da599170dde7319155a729393c1188d7b706e470b9a8324
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),
('double gutshot', {'cards': ['7h', '9d', 'Tc', 'Js', 'Kh', '2c'], '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),
('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)],
[('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),
('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),
('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),
('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),
('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),
('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)]]
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 |
| double gutshot | 8 | 8 | Passed |
SHA-256 / a7e0edc497747e66c097a5468b2f0888cc346ddc76a67ea2bdc2a76800e3f66c
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.735938+00:00.
Case digest / 35bf25eef2f3617f24ee420d803c3f5007a92c65a1c2816639560a5eff57d766