FAILURE MAP
← Case archive

FA-82076 / Poker hand evaluation / Open access

Ace-to-five wheel treated as a straight in deuce-to-seven · case 01

A-2-3-4-5 is scored as a straight, losing to king-high hands it should beat and never being compared as ace high.

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

ROOT CAUSE

The high-hand wheel rule is copied into the lowball evaluator where the ace is always high.

THE FAILURE

The high-hand wheel rule is copied into the lowball evaluator where the ace is always high.

Unsuccessful approach: Treating an ace-to-deuce span as a straight marks any A-x-x-x-2 hand as a straight.

Case contract

Input: [hand_a, hand_b] five distinct cards each. Deuce-to-seven lowball: aces are always high, A-2-3-4-5 is not a straight, straights and flushes count against the hand, and the standard high-hand ordering is inverted so the weaker high hand wins. Return 1 if hand_a wins, -1 if hand_b wins, 0 for a tie.

Why this case matters

Lowball variants reuse high-hand evaluators with inverted outcomes, a common source of subtle bugs.

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'
    def key(h):
        vals=sorted((R.index(c[0])+2 for c in h), reverse=True)
        cnt=collections.Counter(vals)
        order=sorted(cnt, key=lambda v:(cnt[v],v), reverse=True)
        shape=sorted(cnt.values(), reverse=True)
        straight=len(cnt)==5 and (vals[0]-vals[4]==4 or vals==[14,5,4,3,2])
        flush=len({c[1] for c in h})==1
        if straight and flush: return (8,vals)
        if shape==[4,1]: return (7,order)
        if shape==[3,2]: return (6,order)
        if flush: return (5,vals)
        if straight: return (4,vals)
        if shape==[3,1,1]: return (3,order)
        if shape==[2,2,1]: return (2,order)
        if shape==[2,1,1,1]: return (1,order)
        return (0,vals)
    ka,kb=key(x[0]),key(x[1])
    if ka==kb: return 0
    return 1 if ka<kb else -1
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('number one vs wheel', [['7h', '5d', '4c', '3s', '2h'], ['Ah', '2d', '3c', '4s', '5h']], 1),
  ('wheel is ace high', [['Ah', '2d', '3c', '4s', '5h'], ['Kh', 'Qd', 'Jc', '9s', '8h']], -1),
  ('seven low vs eight low', [['8h', '6d', '4c', '3s', '2h'], ['7c', '6h', '4d', '3c', '2d']], -1),
  ('flush counts against', [['2h', '4h', '5h', '6h', '8h'], ['9c', '6d', '4d', '3c', '2d']], -1),
  ('straight counts against', [['3h', '4d', '5c', '6s', '7h'], ['Kh', 'Qd', 'Jc', '9s', '7c']], -1),
  ('pair loses to king high', [['2h', '2d', '4c', '5s', '7h'], ['Kh', '8d', '6c', '4s', '3h']], -1),
  ('wheel vs pair', [['Ah', '2d', '3c', '4s', '5h'], ['3h', '3d', '6c', '8s', '9h']], 1),
  ('ace-deuce span vs pair', [['Ah', 'Jd', '8c', '6s', '2h'], ['4h', '4d', '6d', '8d', '9s']], 1)],
 [('flush counts against', [['2h', '4h', '5h', '6h', '8h'], ['9c', '6d', '4d', '3c', '2d']], -1),
  ('straight counts against', [['3h', '4d', '5c', '6s', '7h'], ['Kh', 'Qd', 'Jc', '9s', '7c']], -1),
  ('pair loses to king high', [['2h', '2d', '4c', '5s', '7h'], ['Kh', '8d', '6c', '4s', '3h']], -1),
  ('ace-king gap hand', [['Ah', 'Kd', '7c', '4s', '2h'], ['Qh', 'Jd', 'Tc', '8s', '6h']], -1),
  ('straight flush vs flush', [['2c', '3c', '4c', '5c', '6c'], ['9d', '7d', '5d', '3d', '2d']], -1),
  ('tie', [['7h', '5d', '4c', '3s', '2h'], ['7c', '5h', '4d', '3c', '2d']], 0),
  ('wheel vs pair', [['Ah', '2d', '3c', '4s', '5h'], ['3h', '3d', '6c', '8s', '9h']], 1),
  ('ace-deuce span vs pair', [['Ah', 'Jd', '8c', '6s', '2h'], ['4h', '4d', '6d', '8d', '9s']], 1)],
 [('ace-king gap hand', [['Ah', 'Kd', '7c', '4s', '2h'], ['Qh', 'Jd', 'Tc', '8s', '6h']], -1),
  ('straight flush vs flush', [['2c', '3c', '4c', '5c', '6c'], ['9d', '7d', '5d', '3d', '2d']], -1),
  ('tie', [['7h', '5d', '4c', '3s', '2h'], ['7c', '5h', '4d', '3c', '2d']], 0),
  ('ace high vs pair', [['Ah', 'Qd', '9c', '7s', '5h'], ['3h', '3d', '6c', '5s', '4h']], 1),
  ('both pairs lower pair wins', [['4h', '4d', 'Kc', 'Qs', 'Jh'], ['5h', '5d', '2c', '3s', '7h']],
   1),
  ('wheel vs pair', [['Ah', '2d', '3c', '4s', '5h'], ['3h', '3d', '6c', '8s', '9h']], 1),
  ('ace-deuce span vs pair', [['Ah', 'Jd', '8c', '6s', '2h'], ['4h', '4d', '6d', '8d', '9s']], 1),
  ('ace high vs king high', [['Ah', '9d', '7c', '4s', '2h'], ['Kh', 'Qd', 'Jc', '9s', '8c']], -1)],
 [('number one vs wheel', [['7h', '5d', '4c', '3s', '2h'], ['Ah', '2d', '3c', '4s', '5h']], 1),
  ('ace high vs pair', [['Ah', 'Qd', '9c', '7s', '5h'], ['3h', '3d', '6c', '5s', '4h']], 1),
  ('both pairs lower pair wins', [['4h', '4d', 'Kc', 'Qs', 'Jh'], ['5h', '5d', '2c', '3s', '7h']],
   1),
  ('wheel vs pair', [['Ah', '2d', '3c', '4s', '5h'], ['3h', '3d', '6c', '8s', '9h']], 1),
  ('ace-deuce span vs pair', [['Ah', 'Jd', '8c', '6s', '2h'], ['4h', '4d', '6d', '8d', '9s']], 1),
  ('ace high vs king high', [['Ah', '9d', '7c', '4s', '2h'], ['Kh', 'Qd', 'Jc', '9s', '8c']], -1),
  ('second tie', [['Kh', 'Jd', '9c', '6s', '3h'], ['Kc', 'Jh', '9d', '6c', '3d']], 0),
  ('nine vs ten', [['9h', '7d', '5c', '3s', '2h'], ['Th', '4d', '3c', '6s', '2c']], 1)],
 [('number one vs wheel', [['7h', '5d', '4c', '3s', '2h'], ['Ah', '2d', '3c', '4s', '5h']], 1),
  ('wheel is ace high', [['Ah', '2d', '3c', '4s', '5h'], ['Kh', 'Qd', 'Jc', '9s', '8h']], -1),
  ('seven low vs eight low', [['8h', '6d', '4c', '3s', '2h'], ['7c', '6h', '4d', '3c', '2d']], -1),
  ('flush counts against', [['2h', '4h', '5h', '6h', '8h'], ['9c', '6d', '4d', '3c', '2d']], -1),
  ('wheel vs pair', [['Ah', '2d', '3c', '4s', '5h'], ['3h', '3d', '6c', '8s', '9h']], 1),
  ('ace-deuce span vs pair', [['Ah', 'Jd', '8c', '6s', '2h'], ['4h', '4d', '6d', '8d', '9s']], 1),
  ('second tie', [['Kh', 'Jd', '9c', '6s', '3h'], ['Kc', 'Jh', '9d', '6c', '3d']], 0),
  ('nine vs ten', [['9h', '7d', '5c', '3s', '2h'], ['Th', '4d', '3c', '6s', '2c']], 1)]]
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 fixtureActualExpectedOutcome
number one vs wheel11Passed
wheel is ace high-1-1Passed
seven low vs eight low-1-1Passed
flush counts against-1-1Passed
straight counts against-1-1Passed
pair loses to king high-1-1Passed
wheel vs pair-11Failed
ace-deuce span vs pair11Passed

SHA-256 / 43a16acfd52cbb4985f01ce61aa4c67da2f845ac7e845527750ace96b52acc30

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'
    def key(h):
        vals=sorted((R.index(c[0])+2 for c in h), reverse=True)
        cnt=collections.Counter(vals)
        order=sorted(cnt, key=lambda v:(cnt[v],v), reverse=True)
        shape=sorted(cnt.values(), reverse=True)
        straight=len(cnt)==5 and (vals[0]-vals[4]==4 or vals[0]-vals[4]==12)
        flush=len({c[1] for c in h})==1
        if straight and flush: return (8,vals)
        if shape==[4,1]: return (7,order)
        if shape==[3,2]: return (6,order)
        if flush: return (5,vals)
        if straight: return (4,vals)
        if shape==[3,1,1]: return (3,order)
        if shape==[2,2,1]: return (2,order)
        if shape==[2,1,1,1]: return (1,order)
        return (0,vals)
    ka,kb=key(x[0]),key(x[1])
    if ka==kb: return 0
    return 1 if ka<kb else -1
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('number one vs wheel', [['7h', '5d', '4c', '3s', '2h'], ['Ah', '2d', '3c', '4s', '5h']], 1),
  ('wheel is ace high', [['Ah', '2d', '3c', '4s', '5h'], ['Kh', 'Qd', 'Jc', '9s', '8h']], -1),
  ('seven low vs eight low', [['8h', '6d', '4c', '3s', '2h'], ['7c', '6h', '4d', '3c', '2d']], -1),
  ('flush counts against', [['2h', '4h', '5h', '6h', '8h'], ['9c', '6d', '4d', '3c', '2d']], -1),
  ('straight counts against', [['3h', '4d', '5c', '6s', '7h'], ['Kh', 'Qd', 'Jc', '9s', '7c']], -1),
  ('pair loses to king high', [['2h', '2d', '4c', '5s', '7h'], ['Kh', '8d', '6c', '4s', '3h']], -1),
  ('wheel vs pair', [['Ah', '2d', '3c', '4s', '5h'], ['3h', '3d', '6c', '8s', '9h']], 1),
  ('ace-deuce span vs pair', [['Ah', 'Jd', '8c', '6s', '2h'], ['4h', '4d', '6d', '8d', '9s']], 1)],
 [('flush counts against', [['2h', '4h', '5h', '6h', '8h'], ['9c', '6d', '4d', '3c', '2d']], -1),
  ('straight counts against', [['3h', '4d', '5c', '6s', '7h'], ['Kh', 'Qd', 'Jc', '9s', '7c']], -1),
  ('pair loses to king high', [['2h', '2d', '4c', '5s', '7h'], ['Kh', '8d', '6c', '4s', '3h']], -1),
  ('ace-king gap hand', [['Ah', 'Kd', '7c', '4s', '2h'], ['Qh', 'Jd', 'Tc', '8s', '6h']], -1),
  ('straight flush vs flush', [['2c', '3c', '4c', '5c', '6c'], ['9d', '7d', '5d', '3d', '2d']], -1),
  ('tie', [['7h', '5d', '4c', '3s', '2h'], ['7c', '5h', '4d', '3c', '2d']], 0),
  ('wheel vs pair', [['Ah', '2d', '3c', '4s', '5h'], ['3h', '3d', '6c', '8s', '9h']], 1),
  ('ace-deuce span vs pair', [['Ah', 'Jd', '8c', '6s', '2h'], ['4h', '4d', '6d', '8d', '9s']], 1)],
 [('ace-king gap hand', [['Ah', 'Kd', '7c', '4s', '2h'], ['Qh', 'Jd', 'Tc', '8s', '6h']], -1),
  ('straight flush vs flush', [['2c', '3c', '4c', '5c', '6c'], ['9d', '7d', '5d', '3d', '2d']], -1),
  ('tie', [['7h', '5d', '4c', '3s', '2h'], ['7c', '5h', '4d', '3c', '2d']], 0),
  ('ace high vs pair', [['Ah', 'Qd', '9c', '7s', '5h'], ['3h', '3d', '6c', '5s', '4h']], 1),
  ('both pairs lower pair wins', [['4h', '4d', 'Kc', 'Qs', 'Jh'], ['5h', '5d', '2c', '3s', '7h']],
   1),
  ('wheel vs pair', [['Ah', '2d', '3c', '4s', '5h'], ['3h', '3d', '6c', '8s', '9h']], 1),
  ('ace-deuce span vs pair', [['Ah', 'Jd', '8c', '6s', '2h'], ['4h', '4d', '6d', '8d', '9s']], 1),
  ('ace high vs king high', [['Ah', '9d', '7c', '4s', '2h'], ['Kh', 'Qd', 'Jc', '9s', '8c']], -1)],
 [('number one vs wheel', [['7h', '5d', '4c', '3s', '2h'], ['Ah', '2d', '3c', '4s', '5h']], 1),
  ('ace high vs pair', [['Ah', 'Qd', '9c', '7s', '5h'], ['3h', '3d', '6c', '5s', '4h']], 1),
  ('both pairs lower pair wins', [['4h', '4d', 'Kc', 'Qs', 'Jh'], ['5h', '5d', '2c', '3s', '7h']],
   1),
  ('wheel vs pair', [['Ah', '2d', '3c', '4s', '5h'], ['3h', '3d', '6c', '8s', '9h']], 1),
  ('ace-deuce span vs pair', [['Ah', 'Jd', '8c', '6s', '2h'], ['4h', '4d', '6d', '8d', '9s']], 1),
  ('ace high vs king high', [['Ah', '9d', '7c', '4s', '2h'], ['Kh', 'Qd', 'Jc', '9s', '8c']], -1),
  ('second tie', [['Kh', 'Jd', '9c', '6s', '3h'], ['Kc', 'Jh', '9d', '6c', '3d']], 0),
  ('nine vs ten', [['9h', '7d', '5c', '3s', '2h'], ['Th', '4d', '3c', '6s', '2c']], 1)],
 [('number one vs wheel', [['7h', '5d', '4c', '3s', '2h'], ['Ah', '2d', '3c', '4s', '5h']], 1),
  ('wheel is ace high', [['Ah', '2d', '3c', '4s', '5h'], ['Kh', 'Qd', 'Jc', '9s', '8h']], -1),
  ('seven low vs eight low', [['8h', '6d', '4c', '3s', '2h'], ['7c', '6h', '4d', '3c', '2d']], -1),
  ('flush counts against', [['2h', '4h', '5h', '6h', '8h'], ['9c', '6d', '4d', '3c', '2d']], -1),
  ('wheel vs pair', [['Ah', '2d', '3c', '4s', '5h'], ['3h', '3d', '6c', '8s', '9h']], 1),
  ('ace-deuce span vs pair', [['Ah', 'Jd', '8c', '6s', '2h'], ['4h', '4d', '6d', '8d', '9s']], 1),
  ('second tie', [['Kh', 'Jd', '9c', '6s', '3h'], ['Kc', 'Jh', '9d', '6c', '3d']], 0),
  ('nine vs ten', [['9h', '7d', '5c', '3s', '2h'], ['Th', '4d', '3c', '6s', '2c']], 1)]]
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 fixtureActualExpectedOutcome
number one vs wheel11Passed
wheel is ace high-1-1Passed
seven low vs eight low-1-1Passed
flush counts against-1-1Passed
straight counts against-1-1Passed
pair loses to king high-1-1Passed
wheel vs pair-11Failed
ace-deuce span vs pair-11Failed

SHA-256 / b6e45e670468144813d0cf729e60fcd8012abc710b2a54e0fff18aef8869c75e

HELD IN THE MEMBER ARCHIVE

The verified repair and its recorded checks are member-only.

This mechanism has 8 recorded checks per implementation. The open-access tier publishes the failure and the unsuccessful fix; the repaired source that passes every check, and the observations that prove it, are available to members.

Every case sharing this mechanism uses the same contract and the same repair, so this one record is held back for all of them.

Member access is invitation-based. Sign in with your invited account to inspect the repair.

Sign in to the archive ↗

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:08.834345+00:00.

Case digest / 701939ae25da554261c4373e5b00c968c08bbb01e11cb119654d7b5ac0397f1e