FA-82201 / Poker hand evaluation / Open access
Pair announced by the highest card · case 01
A pair of fives with an ace is announced "Pair of Aces".
ROOT CAUSE
The pair name is taken from the highest card instead of the paired rank group.
VERIFIED REPAIR
Use the rank of the first (largest) rank group.
Unsuccessful approach: The second-highest card is the pair only when the pair is on top.
Case contract
Input: five distinct cards. Return the showdown announcement: "Royal Flush", "Straight Flush, <top> high", "Four <plural>", "Full House, <trips plural> full of <pair plural>", "Flush, <top> high", "Straight, <top> high" (wheel is Five high), "Three <plural>", "Two Pair, <higher plural> and <lower plural>", "Pair of <plural>", "High Card, <top>". Rank names Two..Ace; plurals add "s" except Deuces and Sixes.
Why this case matters
Dealer announcements and hand histories must name the same hand the evaluator paid.
1 / The failure
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
import collections
N = 1
observations = []
def solve(x):
R='23456789TJQKA'
NAME={2:'Two',3:'Three',4:'Four',5:'Five',6:'Six',7:'Seven',8:'Eight',9:'Nine',10:'Ten',11:'Jack',12:'Queen',13:'King',14:'Ace'}
def pl(v): return {2:'Deuces',6:'Sixes'}.get(v, NAME[v]+'s')
vals=sorted((R.index(c[0])+2 for c in x), reverse=True)
cnt=collections.Counter(vals)
groups=sorted(cnt, key=lambda v:(cnt[v],v), reverse=True)
shape=sorted(cnt.values(), reverse=True)
flush=len({c[1] for c in x})==1
wheel=vals==[14,5,4,3,2]
straight=len(cnt)==5 and (vals[0]-vals[4]==4 or wheel)
top=5 if wheel else vals[0]
if straight and flush: return 'Royal Flush' if top==14 else 'Straight Flush, %s high' % NAME[top]
if shape==[4,1]: return 'Four %s' % pl(groups[0])
if shape==[3,2]: return 'Full House, %s full of %s' % (pl(groups[0]), pl(groups[1]))
if flush: return 'Flush, %s high' % NAME[vals[0]]
if straight: return 'Straight, %s high' % NAME[top]
if shape==[3,1,1]: return 'Three %s' % pl(groups[0])
if shape==[2,2,1]: return 'Two Pair, %s and %s' % (pl(groups[0]), pl(groups[1]))
if shape==[2,1,1,1]: return 'Pair of %s' % pl(vals[0])
return 'High Card, %s' % NAME[vals[0]]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('pair of sixes', ['6h', '6d', 'Kc', '9s', '2h'], 'Pair of Sixes'),
('pair of deuces', ['2h', '2d', 'Kc', '9s', '5h'], 'Pair of Deuces'),
('wheel', ['Ah', '2d', '3c', '4s', '5h'], 'Straight, Five high'),
('steel wheel', ['As', '2s', '3s', '4s', '5s'], 'Straight Flush, Five high'),
('royal', ['Th', 'Jh', 'Qh', 'Kh', 'Ah'], 'Royal Flush'),
('king-high straight flush', ['9d', 'Td', 'Jd', 'Qd', 'Kd'], 'Straight Flush, King high'),
('threes full of kings', ['3h', '3d', '3c', 'Ks', 'Kh'], 'Full House, Threes full of Kings'),
('kings full of threes', ['Kh', 'Kd', 'Kc', '3s', '3h'], 'Full House, Kings full of Threes')],
[('pair of deuces', ['2h', '2d', 'Kc', '9s', '5h'], 'Pair of Deuces'),
('king-high straight flush', ['9d', 'Td', 'Jd', 'Qd', 'Kd'], 'Straight Flush, King high'),
('threes full of kings', ['3h', '3d', '3c', 'Ks', 'Kh'], 'Full House, Threes full of Kings'),
('kings full of threes', ['Kh', 'Kd', 'Kc', '3s', '3h'], 'Full House, Kings full of Threes'),
('two pair ace kicker', ['Ah', 'Kd', 'Kc', '7s', '7h'], 'Two Pair, Kings and Sevens'),
('two pair low kicker', ['Kh', 'Kd', '7c', '7s', '2h'], 'Two Pair, Kings and Sevens'),
('pair below high cards', ['Ah', 'Kd', '5c', '5s', '9h'], 'Pair of Fives'),
('high card', ['Ah', 'Jd', '8c', '5s', '3h'], 'High Card, Ace')],
[('pair of sixes', ['6h', '6d', 'Kc', '9s', '2h'], 'Pair of Sixes'),
('two pair ace kicker', ['Ah', 'Kd', 'Kc', '7s', '7h'], 'Two Pair, Kings and Sevens'),
('two pair low kicker', ['Kh', 'Kd', '7c', '7s', '2h'], 'Two Pair, Kings and Sevens'),
('pair below high cards', ['Ah', 'Kd', '5c', '5s', '9h'], 'Pair of Fives'),
('high card', ['Ah', 'Jd', '8c', '5s', '3h'], 'High Card, Ace'),
('four nines', ['9h', '9d', '9c', '9s', '2h'], 'Four Nines'),
('flush', ['2c', '7c', '9c', 'Jc', 'Qc'], 'Flush, Queen high'),
('six-high straight', ['2h', '3d', '4c', '5s', '6h'], 'Straight, Six high')],
[('pair of sixes', ['6h', '6d', 'Kc', '9s', '2h'], 'Pair of Sixes'),
('pair of deuces', ['2h', '2d', 'Kc', '9s', '5h'], 'Pair of Deuces'),
('wheel', ['Ah', '2d', '3c', '4s', '5h'], 'Straight, Five high'),
('pair below high cards', ['Ah', 'Kd', '5c', '5s', '9h'], 'Pair of Fives'),
('four nines', ['9h', '9d', '9c', '9s', '2h'], 'Four Nines'),
('flush', ['2c', '7c', '9c', 'Jc', 'Qc'], 'Flush, Queen high'),
('six-high straight', ['2h', '3d', '4c', '5s', '6h'], 'Straight, Six high'),
('three sixes', ['6h', '6d', '6c', 'Ks', '2h'], 'Three Sixes')],
[('pair of sixes', ['6h', '6d', 'Kc', '9s', '2h'], 'Pair of Sixes'),
('pair of deuces', ['2h', '2d', 'Kc', '9s', '5h'], 'Pair of Deuces'),
('wheel', ['Ah', '2d', '3c', '4s', '5h'], 'Straight, Five high'),
('steel wheel', ['As', '2s', '3s', '4s', '5s'], 'Straight Flush, Five high'),
('royal', ['Th', 'Jh', 'Qh', 'Kh', 'Ah'], 'Royal Flush'),
('king-high straight flush', ['9d', 'Td', 'Jd', 'Qd', 'Kd'], 'Straight Flush, King high'),
('pair below high cards', ['Ah', 'Kd', '5c', '5s', '9h'], 'Pair of Fives'),
('three sixes', ['6h', '6d', '6c', 'Ks', '2h'], 'Three Sixes')]]
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 |
|---|---|---|---|
| pair of sixes | Pair of Kings | Pair of Sixes | Failed |
| pair of deuces | Pair of Kings | Pair of Deuces | Failed |
| wheel | Straight, Five high | Straight, Five high | Passed |
| steel wheel | Straight Flush, Five high | Straight Flush, Five high | Passed |
| royal | Royal Flush | Royal Flush | Passed |
| king-high straight flush | Straight Flush, King high | Straight Flush, King high | Passed |
| threes full of kings | Full House, Threes full of Kings | Full House, Threes full of Kings | Passed |
| kings full of threes | Full House, Kings full of Threes | Full House, Kings full of Threes | Passed |
SHA-256 / 69087945043f1cdbead83da3202f1f6e9d42b343ca08d09b5df89936039332d1
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
import collections
N = 1
observations = []
def solve(x):
R='23456789TJQKA'
NAME={2:'Two',3:'Three',4:'Four',5:'Five',6:'Six',7:'Seven',8:'Eight',9:'Nine',10:'Ten',11:'Jack',12:'Queen',13:'King',14:'Ace'}
def pl(v): return {2:'Deuces',6:'Sixes'}.get(v, NAME[v]+'s')
vals=sorted((R.index(c[0])+2 for c in x), reverse=True)
cnt=collections.Counter(vals)
groups=sorted(cnt, key=lambda v:(cnt[v],v), reverse=True)
shape=sorted(cnt.values(), reverse=True)
flush=len({c[1] for c in x})==1
wheel=vals==[14,5,4,3,2]
straight=len(cnt)==5 and (vals[0]-vals[4]==4 or wheel)
top=5 if wheel else vals[0]
if straight and flush: return 'Royal Flush' if top==14 else 'Straight Flush, %s high' % NAME[top]
if shape==[4,1]: return 'Four %s' % pl(groups[0])
if shape==[3,2]: return 'Full House, %s full of %s' % (pl(groups[0]), pl(groups[1]))
if flush: return 'Flush, %s high' % NAME[vals[0]]
if straight: return 'Straight, %s high' % NAME[top]
if shape==[3,1,1]: return 'Three %s' % pl(groups[0])
if shape==[2,2,1]: return 'Two Pair, %s and %s' % (pl(groups[0]), pl(groups[1]))
if shape==[2,1,1,1]: return 'Pair of %s' % pl(vals[1])
return 'High Card, %s' % NAME[vals[0]]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('pair of sixes', ['6h', '6d', 'Kc', '9s', '2h'], 'Pair of Sixes'),
('pair of deuces', ['2h', '2d', 'Kc', '9s', '5h'], 'Pair of Deuces'),
('wheel', ['Ah', '2d', '3c', '4s', '5h'], 'Straight, Five high'),
('steel wheel', ['As', '2s', '3s', '4s', '5s'], 'Straight Flush, Five high'),
('royal', ['Th', 'Jh', 'Qh', 'Kh', 'Ah'], 'Royal Flush'),
('king-high straight flush', ['9d', 'Td', 'Jd', 'Qd', 'Kd'], 'Straight Flush, King high'),
('threes full of kings', ['3h', '3d', '3c', 'Ks', 'Kh'], 'Full House, Threes full of Kings'),
('kings full of threes', ['Kh', 'Kd', 'Kc', '3s', '3h'], 'Full House, Kings full of Threes')],
[('pair of deuces', ['2h', '2d', 'Kc', '9s', '5h'], 'Pair of Deuces'),
('king-high straight flush', ['9d', 'Td', 'Jd', 'Qd', 'Kd'], 'Straight Flush, King high'),
('threes full of kings', ['3h', '3d', '3c', 'Ks', 'Kh'], 'Full House, Threes full of Kings'),
('kings full of threes', ['Kh', 'Kd', 'Kc', '3s', '3h'], 'Full House, Kings full of Threes'),
('two pair ace kicker', ['Ah', 'Kd', 'Kc', '7s', '7h'], 'Two Pair, Kings and Sevens'),
('two pair low kicker', ['Kh', 'Kd', '7c', '7s', '2h'], 'Two Pair, Kings and Sevens'),
('pair below high cards', ['Ah', 'Kd', '5c', '5s', '9h'], 'Pair of Fives'),
('high card', ['Ah', 'Jd', '8c', '5s', '3h'], 'High Card, Ace')],
[('pair of sixes', ['6h', '6d', 'Kc', '9s', '2h'], 'Pair of Sixes'),
('two pair ace kicker', ['Ah', 'Kd', 'Kc', '7s', '7h'], 'Two Pair, Kings and Sevens'),
('two pair low kicker', ['Kh', 'Kd', '7c', '7s', '2h'], 'Two Pair, Kings and Sevens'),
('pair below high cards', ['Ah', 'Kd', '5c', '5s', '9h'], 'Pair of Fives'),
('high card', ['Ah', 'Jd', '8c', '5s', '3h'], 'High Card, Ace'),
('four nines', ['9h', '9d', '9c', '9s', '2h'], 'Four Nines'),
('flush', ['2c', '7c', '9c', 'Jc', 'Qc'], 'Flush, Queen high'),
('six-high straight', ['2h', '3d', '4c', '5s', '6h'], 'Straight, Six high')],
[('pair of sixes', ['6h', '6d', 'Kc', '9s', '2h'], 'Pair of Sixes'),
('pair of deuces', ['2h', '2d', 'Kc', '9s', '5h'], 'Pair of Deuces'),
('wheel', ['Ah', '2d', '3c', '4s', '5h'], 'Straight, Five high'),
('pair below high cards', ['Ah', 'Kd', '5c', '5s', '9h'], 'Pair of Fives'),
('four nines', ['9h', '9d', '9c', '9s', '2h'], 'Four Nines'),
('flush', ['2c', '7c', '9c', 'Jc', 'Qc'], 'Flush, Queen high'),
('six-high straight', ['2h', '3d', '4c', '5s', '6h'], 'Straight, Six high'),
('three sixes', ['6h', '6d', '6c', 'Ks', '2h'], 'Three Sixes')],
[('pair of sixes', ['6h', '6d', 'Kc', '9s', '2h'], 'Pair of Sixes'),
('pair of deuces', ['2h', '2d', 'Kc', '9s', '5h'], 'Pair of Deuces'),
('wheel', ['Ah', '2d', '3c', '4s', '5h'], 'Straight, Five high'),
('steel wheel', ['As', '2s', '3s', '4s', '5s'], 'Straight Flush, Five high'),
('royal', ['Th', 'Jh', 'Qh', 'Kh', 'Ah'], 'Royal Flush'),
('king-high straight flush', ['9d', 'Td', 'Jd', 'Qd', 'Kd'], 'Straight Flush, King high'),
('pair below high cards', ['Ah', 'Kd', '5c', '5s', '9h'], 'Pair of Fives'),
('three sixes', ['6h', '6d', '6c', 'Ks', '2h'], 'Three Sixes')]]
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 |
|---|---|---|---|
| pair of sixes | Pair of Nines | Pair of Sixes | Failed |
| pair of deuces | Pair of Nines | Pair of Deuces | Failed |
| wheel | Straight, Five high | Straight, Five high | Passed |
| steel wheel | Straight Flush, Five high | Straight Flush, Five high | Passed |
| royal | Royal Flush | Royal Flush | Passed |
| king-high straight flush | Straight Flush, King high | Straight Flush, King high | Passed |
| threes full of kings | Full House, Threes full of Kings | Full House, Threes full of Kings | Passed |
| kings full of threes | Full House, Kings full of Threes | Full House, Kings full of Threes | Passed |
SHA-256 / 5e176af08edd9056b5aa8034283068f3fceae7768e19d4ca933c3d316d8f0c7e
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
import collections
N = 1
observations = []
def solve(x):
R='23456789TJQKA'
NAME={2:'Two',3:'Three',4:'Four',5:'Five',6:'Six',7:'Seven',8:'Eight',9:'Nine',10:'Ten',11:'Jack',12:'Queen',13:'King',14:'Ace'}
def pl(v): return {2:'Deuces',6:'Sixes'}.get(v, NAME[v]+'s')
vals=sorted((R.index(c[0])+2 for c in x), reverse=True)
cnt=collections.Counter(vals)
groups=sorted(cnt, key=lambda v:(cnt[v],v), reverse=True)
shape=sorted(cnt.values(), reverse=True)
flush=len({c[1] for c in x})==1
wheel=vals==[14,5,4,3,2]
straight=len(cnt)==5 and (vals[0]-vals[4]==4 or wheel)
top=5 if wheel else vals[0]
if straight and flush: return 'Royal Flush' if top==14 else 'Straight Flush, %s high' % NAME[top]
if shape==[4,1]: return 'Four %s' % pl(groups[0])
if shape==[3,2]: return 'Full House, %s full of %s' % (pl(groups[0]), pl(groups[1]))
if flush: return 'Flush, %s high' % NAME[vals[0]]
if straight: return 'Straight, %s high' % NAME[top]
if shape==[3,1,1]: return 'Three %s' % pl(groups[0])
if shape==[2,2,1]: return 'Two Pair, %s and %s' % (pl(groups[0]), pl(groups[1]))
if shape==[2,1,1,1]: return 'Pair of %s' % pl(groups[0])
return 'High Card, %s' % NAME[vals[0]]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('pair of sixes', ['6h', '6d', 'Kc', '9s', '2h'], 'Pair of Sixes'),
('pair of deuces', ['2h', '2d', 'Kc', '9s', '5h'], 'Pair of Deuces'),
('wheel', ['Ah', '2d', '3c', '4s', '5h'], 'Straight, Five high'),
('steel wheel', ['As', '2s', '3s', '4s', '5s'], 'Straight Flush, Five high'),
('royal', ['Th', 'Jh', 'Qh', 'Kh', 'Ah'], 'Royal Flush'),
('king-high straight flush', ['9d', 'Td', 'Jd', 'Qd', 'Kd'], 'Straight Flush, King high'),
('threes full of kings', ['3h', '3d', '3c', 'Ks', 'Kh'], 'Full House, Threes full of Kings'),
('kings full of threes', ['Kh', 'Kd', 'Kc', '3s', '3h'], 'Full House, Kings full of Threes')],
[('pair of deuces', ['2h', '2d', 'Kc', '9s', '5h'], 'Pair of Deuces'),
('king-high straight flush', ['9d', 'Td', 'Jd', 'Qd', 'Kd'], 'Straight Flush, King high'),
('threes full of kings', ['3h', '3d', '3c', 'Ks', 'Kh'], 'Full House, Threes full of Kings'),
('kings full of threes', ['Kh', 'Kd', 'Kc', '3s', '3h'], 'Full House, Kings full of Threes'),
('two pair ace kicker', ['Ah', 'Kd', 'Kc', '7s', '7h'], 'Two Pair, Kings and Sevens'),
('two pair low kicker', ['Kh', 'Kd', '7c', '7s', '2h'], 'Two Pair, Kings and Sevens'),
('pair below high cards', ['Ah', 'Kd', '5c', '5s', '9h'], 'Pair of Fives'),
('high card', ['Ah', 'Jd', '8c', '5s', '3h'], 'High Card, Ace')],
[('pair of sixes', ['6h', '6d', 'Kc', '9s', '2h'], 'Pair of Sixes'),
('two pair ace kicker', ['Ah', 'Kd', 'Kc', '7s', '7h'], 'Two Pair, Kings and Sevens'),
('two pair low kicker', ['Kh', 'Kd', '7c', '7s', '2h'], 'Two Pair, Kings and Sevens'),
('pair below high cards', ['Ah', 'Kd', '5c', '5s', '9h'], 'Pair of Fives'),
('high card', ['Ah', 'Jd', '8c', '5s', '3h'], 'High Card, Ace'),
('four nines', ['9h', '9d', '9c', '9s', '2h'], 'Four Nines'),
('flush', ['2c', '7c', '9c', 'Jc', 'Qc'], 'Flush, Queen high'),
('six-high straight', ['2h', '3d', '4c', '5s', '6h'], 'Straight, Six high')],
[('pair of sixes', ['6h', '6d', 'Kc', '9s', '2h'], 'Pair of Sixes'),
('pair of deuces', ['2h', '2d', 'Kc', '9s', '5h'], 'Pair of Deuces'),
('wheel', ['Ah', '2d', '3c', '4s', '5h'], 'Straight, Five high'),
('pair below high cards', ['Ah', 'Kd', '5c', '5s', '9h'], 'Pair of Fives'),
('four nines', ['9h', '9d', '9c', '9s', '2h'], 'Four Nines'),
('flush', ['2c', '7c', '9c', 'Jc', 'Qc'], 'Flush, Queen high'),
('six-high straight', ['2h', '3d', '4c', '5s', '6h'], 'Straight, Six high'),
('three sixes', ['6h', '6d', '6c', 'Ks', '2h'], 'Three Sixes')],
[('pair of sixes', ['6h', '6d', 'Kc', '9s', '2h'], 'Pair of Sixes'),
('pair of deuces', ['2h', '2d', 'Kc', '9s', '5h'], 'Pair of Deuces'),
('wheel', ['Ah', '2d', '3c', '4s', '5h'], 'Straight, Five high'),
('steel wheel', ['As', '2s', '3s', '4s', '5s'], 'Straight Flush, Five high'),
('royal', ['Th', 'Jh', 'Qh', 'Kh', 'Ah'], 'Royal Flush'),
('king-high straight flush', ['9d', 'Td', 'Jd', 'Qd', 'Kd'], 'Straight Flush, King high'),
('pair below high cards', ['Ah', 'Kd', '5c', '5s', '9h'], 'Pair of Fives'),
('three sixes', ['6h', '6d', '6c', 'Ks', '2h'], 'Three Sixes')]]
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 |
|---|---|---|---|
| pair of sixes | Pair of Sixes | Pair of Sixes | Passed |
| pair of deuces | Pair of Deuces | Pair of Deuces | Passed |
| wheel | Straight, Five high | Straight, Five high | Passed |
| steel wheel | Straight Flush, Five high | Straight Flush, Five high | Passed |
| royal | Royal Flush | Royal Flush | Passed |
| king-high straight flush | Straight Flush, King high | Straight Flush, King high | Passed |
| threes full of kings | Full House, Threes full of Kings | Full House, Threes full of Kings | Passed |
| kings full of threes | Full House, Kings full of Threes | Full House, Kings full of Threes | Passed |
SHA-256 / 468e91bcb2b473c7c3150b901566edf81a42255b67d68d2adef3f27e02dfdb93
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.062788+00:00.
Case digest / 43ba72aa56a94c160d4d0bfc924b520a2cbbef5a861d9374ad0ff352950569b8