FAILURE MAP
← Case archive

FA-82316 / Poker hand evaluation / Open access

Worst qualifying subset chosen for a badugi · case 01

A three-card hand is valued by its highest valid subset rather than its lowest.

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

ROOT CAUSE

The evaluator keeps the maximum candidate, but lower is better in badugi.

VERIFIED REPAIR

Choose the minimum candidate among subsets of the best size.

Unsuccessful approach: Taking the first candidate depends on card order, not value.

Case contract

Input: [hand_a, hand_b], four distinct cards each. A hand's value is its best subset with all ranks distinct and all suits distinct: more cards beat fewer; among equal sizes the lower subset (compared from its highest card down, ace low = 1) wins. Return 1, -1 or 0.

Why this case matters

Badugi uses a unique subset-based evaluator that is easy to get subtly wrong.

1 / The failure

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json
import itertools
N = 1
observations = []
def solve(x):
    R='A23456789TJQK'
    def best(h):
        for n in range(4,0,-1):
            cands=[]
            for sub in itertools.combinations(h,n):
                if len({c[0] for c in sub})==n and len({c[1] for c in sub})==n:
                    cands.append(sorted((R.index(c[0])+1 for c in sub), reverse=True))
            if cands: return (n, max(cands))
    a,b=best(x[0]),best(x[1])
    if a[0]!=b[0]: return 1 if a[0]>b[0] else -1
    if a[1]==b[1]: return 0
    return 1 if a[1]<b[1] else -1
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('four-card badugi vs three', [['Ac', '2d', '3h', '4s'], ['Ac', '2c', '3h', '4s']], 1),
  ('paired rank different suits', [['Ac', 'Ad', '3h', '4s'], ['5c', '6d', '7h', 'Ks']], -1),
  ('lower badugi wins', [['Ac', '2d', '3h', '8s'], ['Ac', '2d', '4h', '7s']], -1),
  ('equal badugis', [['Ac', '2d', '3h', '4s'], ['Ad', '2c', '3s', '4h']], 0),
  ('best three-card subset', [['Kc', '2c', '3h', '4s'], ['5c', '6c', '7h', '8s']], 1),
  ('two-card hands', [['Ac', '2c', '3c', 'Kd'], ['4h', '5h', '6h', '7s']], -1),
  ('king high badugi vs three', [['Kc', 'Qd', 'Jh', 'Ts'], ['Ac', '2c', '3d', '4h']], 1),
  ('lowest card trap', [['Ac', '5d', '6h', '7s'], ['2c', '3d', '4h', '8s']], 1)],
 [('four-card badugi vs three', [['Ac', '2d', '3h', '4s'], ['Ac', '2c', '3h', '4s']], 1),
  ('equal badugis', [['Ac', '2d', '3h', '4s'], ['Ad', '2c', '3s', '4h']], 0),
  ('best three-card subset', [['Kc', '2c', '3h', '4s'], ['5c', '6c', '7h', '8s']], 1),
  ('two-card hands', [['Ac', '2c', '3c', 'Kd'], ['4h', '5h', '6h', '7s']], -1),
  ('king high badugi vs three', [['Kc', 'Qd', 'Jh', 'Ts'], ['Ac', '2c', '3d', '4h']], 1),
  ('lowest card trap', [['Ac', '5d', '6h', '7s'], ['2c', '3d', '4h', '8s']], 1),
  ('one-card hands', [['Ac', '2c', '3c', '4c'], ['5d', '6d', '7d', '8d']], 1),
  ('suit pair plus rank pair', [['2c', '2d', '5c', '9h'], ['3c', '4c', '6d', 'Th']], 1)],
 [('four-card badugi vs three', [['Ac', '2d', '3h', '4s'], ['Ac', '2c', '3h', '4s']], 1),
  ('paired rank different suits', [['Ac', 'Ad', '3h', '4s'], ['5c', '6d', '7h', 'Ks']], -1),
  ('lower badugi wins', [['Ac', '2d', '3h', '8s'], ['Ac', '2d', '4h', '7s']], -1),
  ('equal badugis', [['Ac', '2d', '3h', '4s'], ['Ad', '2c', '3s', '4h']], 0),
  ('best three-card subset', [['Kc', '2c', '3h', '4s'], ['5c', '6c', '7h', '8s']], 1),
  ('lowest card trap', [['Ac', '5d', '6h', '7s'], ['2c', '3d', '4h', '8s']], 1),
  ('one-card hands', [['Ac', '2c', '3c', '4c'], ['5d', '6d', '7d', '8d']], 1),
  ('suit pair plus rank pair', [['2c', '2d', '5c', '9h'], ['3c', '4c', '6d', 'Th']], 1)],
 [('four-card badugi vs three', [['Ac', '2d', '3h', '4s'], ['Ac', '2c', '3h', '4s']], 1),
  ('paired rank different suits', [['Ac', 'Ad', '3h', '4s'], ['5c', '6d', '7h', 'Ks']], -1),
  ('lower badugi wins', [['Ac', '2d', '3h', '8s'], ['Ac', '2d', '4h', '7s']], -1),
  ('equal badugis', [['Ac', '2d', '3h', '4s'], ['Ad', '2c', '3s', '4h']], 0),
  ('best three-card subset', [['Kc', '2c', '3h', '4s'], ['5c', '6c', '7h', '8s']], 1),
  ('two-card hands', [['Ac', '2c', '3c', 'Kd'], ['4h', '5h', '6h', '7s']], -1),
  ('king high badugi vs three', [['Kc', 'Qd', 'Jh', 'Ts'], ['Ac', '2c', '3d', '4h']], 1),
  ('lowest card trap', [['Ac', '5d', '6h', '7s'], ['2c', '3d', '4h', '8s']], 1)],
 [('lower badugi wins', [['Ac', '2d', '3h', '8s'], ['Ac', '2d', '4h', '7s']], -1),
  ('equal badugis', [['Ac', '2d', '3h', '4s'], ['Ad', '2c', '3s', '4h']], 0),
  ('best three-card subset', [['Kc', '2c', '3h', '4s'], ['5c', '6c', '7h', '8s']], 1),
  ('two-card hands', [['Ac', '2c', '3c', 'Kd'], ['4h', '5h', '6h', '7s']], -1),
  ('king high badugi vs three', [['Kc', 'Qd', 'Jh', 'Ts'], ['Ac', '2c', '3d', '4h']], 1),
  ('lowest card trap', [['Ac', '5d', '6h', '7s'], ['2c', '3d', '4h', '8s']], 1),
  ('one-card hands', [['Ac', '2c', '3c', '4c'], ['5d', '6d', '7d', '8d']], 1),
  ('suit pair plus rank pair', [['2c', '2d', '5c', '9h'], ['3c', '4c', '6d', 'Th']], 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
four-card badugi vs three11Passed
paired rank different suits-1-1Passed
lower badugi wins-1-1Passed
equal badugis00Passed
best three-card subset-11Failed
two-card hands-1-1Passed
king high badugi vs three11Passed
lowest card trap11Passed

SHA-256 / 5f3048d9f42d552e8c57454b8449c23c1f486981097d1b601d08429a8bf6b0c5

2 / The unsuccessful fix

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json
import itertools
N = 1
observations = []
def solve(x):
    R='A23456789TJQK'
    def best(h):
        for n in range(4,0,-1):
            cands=[]
            for sub in itertools.combinations(h,n):
                if len({c[0] for c in sub})==n and len({c[1] for c in sub})==n:
                    cands.append(sorted((R.index(c[0])+1 for c in sub), reverse=True))
            if cands: return (n, cands[0])
    a,b=best(x[0]),best(x[1])
    if a[0]!=b[0]: return 1 if a[0]>b[0] else -1
    if a[1]==b[1]: return 0
    return 1 if a[1]<b[1] else -1
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('four-card badugi vs three', [['Ac', '2d', '3h', '4s'], ['Ac', '2c', '3h', '4s']], 1),
  ('paired rank different suits', [['Ac', 'Ad', '3h', '4s'], ['5c', '6d', '7h', 'Ks']], -1),
  ('lower badugi wins', [['Ac', '2d', '3h', '8s'], ['Ac', '2d', '4h', '7s']], -1),
  ('equal badugis', [['Ac', '2d', '3h', '4s'], ['Ad', '2c', '3s', '4h']], 0),
  ('best three-card subset', [['Kc', '2c', '3h', '4s'], ['5c', '6c', '7h', '8s']], 1),
  ('two-card hands', [['Ac', '2c', '3c', 'Kd'], ['4h', '5h', '6h', '7s']], -1),
  ('king high badugi vs three', [['Kc', 'Qd', 'Jh', 'Ts'], ['Ac', '2c', '3d', '4h']], 1),
  ('lowest card trap', [['Ac', '5d', '6h', '7s'], ['2c', '3d', '4h', '8s']], 1)],
 [('four-card badugi vs three', [['Ac', '2d', '3h', '4s'], ['Ac', '2c', '3h', '4s']], 1),
  ('equal badugis', [['Ac', '2d', '3h', '4s'], ['Ad', '2c', '3s', '4h']], 0),
  ('best three-card subset', [['Kc', '2c', '3h', '4s'], ['5c', '6c', '7h', '8s']], 1),
  ('two-card hands', [['Ac', '2c', '3c', 'Kd'], ['4h', '5h', '6h', '7s']], -1),
  ('king high badugi vs three', [['Kc', 'Qd', 'Jh', 'Ts'], ['Ac', '2c', '3d', '4h']], 1),
  ('lowest card trap', [['Ac', '5d', '6h', '7s'], ['2c', '3d', '4h', '8s']], 1),
  ('one-card hands', [['Ac', '2c', '3c', '4c'], ['5d', '6d', '7d', '8d']], 1),
  ('suit pair plus rank pair', [['2c', '2d', '5c', '9h'], ['3c', '4c', '6d', 'Th']], 1)],
 [('four-card badugi vs three', [['Ac', '2d', '3h', '4s'], ['Ac', '2c', '3h', '4s']], 1),
  ('paired rank different suits', [['Ac', 'Ad', '3h', '4s'], ['5c', '6d', '7h', 'Ks']], -1),
  ('lower badugi wins', [['Ac', '2d', '3h', '8s'], ['Ac', '2d', '4h', '7s']], -1),
  ('equal badugis', [['Ac', '2d', '3h', '4s'], ['Ad', '2c', '3s', '4h']], 0),
  ('best three-card subset', [['Kc', '2c', '3h', '4s'], ['5c', '6c', '7h', '8s']], 1),
  ('lowest card trap', [['Ac', '5d', '6h', '7s'], ['2c', '3d', '4h', '8s']], 1),
  ('one-card hands', [['Ac', '2c', '3c', '4c'], ['5d', '6d', '7d', '8d']], 1),
  ('suit pair plus rank pair', [['2c', '2d', '5c', '9h'], ['3c', '4c', '6d', 'Th']], 1)],
 [('four-card badugi vs three', [['Ac', '2d', '3h', '4s'], ['Ac', '2c', '3h', '4s']], 1),
  ('paired rank different suits', [['Ac', 'Ad', '3h', '4s'], ['5c', '6d', '7h', 'Ks']], -1),
  ('lower badugi wins', [['Ac', '2d', '3h', '8s'], ['Ac', '2d', '4h', '7s']], -1),
  ('equal badugis', [['Ac', '2d', '3h', '4s'], ['Ad', '2c', '3s', '4h']], 0),
  ('best three-card subset', [['Kc', '2c', '3h', '4s'], ['5c', '6c', '7h', '8s']], 1),
  ('two-card hands', [['Ac', '2c', '3c', 'Kd'], ['4h', '5h', '6h', '7s']], -1),
  ('king high badugi vs three', [['Kc', 'Qd', 'Jh', 'Ts'], ['Ac', '2c', '3d', '4h']], 1),
  ('lowest card trap', [['Ac', '5d', '6h', '7s'], ['2c', '3d', '4h', '8s']], 1)],
 [('lower badugi wins', [['Ac', '2d', '3h', '8s'], ['Ac', '2d', '4h', '7s']], -1),
  ('equal badugis', [['Ac', '2d', '3h', '4s'], ['Ad', '2c', '3s', '4h']], 0),
  ('best three-card subset', [['Kc', '2c', '3h', '4s'], ['5c', '6c', '7h', '8s']], 1),
  ('two-card hands', [['Ac', '2c', '3c', 'Kd'], ['4h', '5h', '6h', '7s']], -1),
  ('king high badugi vs three', [['Kc', 'Qd', 'Jh', 'Ts'], ['Ac', '2c', '3d', '4h']], 1),
  ('lowest card trap', [['Ac', '5d', '6h', '7s'], ['2c', '3d', '4h', '8s']], 1),
  ('one-card hands', [['Ac', '2c', '3c', '4c'], ['5d', '6d', '7d', '8d']], 1),
  ('suit pair plus rank pair', [['2c', '2d', '5c', '9h'], ['3c', '4c', '6d', 'Th']], 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
four-card badugi vs three11Passed
paired rank different suits-1-1Passed
lower badugi wins-1-1Passed
equal badugis00Passed
best three-card subset-11Failed
two-card hands-1-1Passed
king high badugi vs three11Passed
lowest card trap11Passed

SHA-256 / 596a3b779af20ea339dcab2db096b0cb1525db79a12a1aceb0c972a24d282d6f

3 / The verified repair

Exit 0
"""Failure Map reference implementation. Python standard library only."""
import json
import itertools
N = 1
observations = []
def solve(x):
    R='A23456789TJQK'
    def best(h):
        for n in range(4,0,-1):
            cands=[]
            for sub in itertools.combinations(h,n):
                if len({c[0] for c in sub})==n and len({c[1] for c in sub})==n:
                    cands.append(sorted((R.index(c[0])+1 for c in sub), reverse=True))
            if cands: return (n, min(cands))
    a,b=best(x[0]),best(x[1])
    if a[0]!=b[0]: return 1 if a[0]>b[0] else -1
    if a[1]==b[1]: return 0
    return 1 if a[1]<b[1] else -1
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('four-card badugi vs three', [['Ac', '2d', '3h', '4s'], ['Ac', '2c', '3h', '4s']], 1),
  ('paired rank different suits', [['Ac', 'Ad', '3h', '4s'], ['5c', '6d', '7h', 'Ks']], -1),
  ('lower badugi wins', [['Ac', '2d', '3h', '8s'], ['Ac', '2d', '4h', '7s']], -1),
  ('equal badugis', [['Ac', '2d', '3h', '4s'], ['Ad', '2c', '3s', '4h']], 0),
  ('best three-card subset', [['Kc', '2c', '3h', '4s'], ['5c', '6c', '7h', '8s']], 1),
  ('two-card hands', [['Ac', '2c', '3c', 'Kd'], ['4h', '5h', '6h', '7s']], -1),
  ('king high badugi vs three', [['Kc', 'Qd', 'Jh', 'Ts'], ['Ac', '2c', '3d', '4h']], 1),
  ('lowest card trap', [['Ac', '5d', '6h', '7s'], ['2c', '3d', '4h', '8s']], 1)],
 [('four-card badugi vs three', [['Ac', '2d', '3h', '4s'], ['Ac', '2c', '3h', '4s']], 1),
  ('equal badugis', [['Ac', '2d', '3h', '4s'], ['Ad', '2c', '3s', '4h']], 0),
  ('best three-card subset', [['Kc', '2c', '3h', '4s'], ['5c', '6c', '7h', '8s']], 1),
  ('two-card hands', [['Ac', '2c', '3c', 'Kd'], ['4h', '5h', '6h', '7s']], -1),
  ('king high badugi vs three', [['Kc', 'Qd', 'Jh', 'Ts'], ['Ac', '2c', '3d', '4h']], 1),
  ('lowest card trap', [['Ac', '5d', '6h', '7s'], ['2c', '3d', '4h', '8s']], 1),
  ('one-card hands', [['Ac', '2c', '3c', '4c'], ['5d', '6d', '7d', '8d']], 1),
  ('suit pair plus rank pair', [['2c', '2d', '5c', '9h'], ['3c', '4c', '6d', 'Th']], 1)],
 [('four-card badugi vs three', [['Ac', '2d', '3h', '4s'], ['Ac', '2c', '3h', '4s']], 1),
  ('paired rank different suits', [['Ac', 'Ad', '3h', '4s'], ['5c', '6d', '7h', 'Ks']], -1),
  ('lower badugi wins', [['Ac', '2d', '3h', '8s'], ['Ac', '2d', '4h', '7s']], -1),
  ('equal badugis', [['Ac', '2d', '3h', '4s'], ['Ad', '2c', '3s', '4h']], 0),
  ('best three-card subset', [['Kc', '2c', '3h', '4s'], ['5c', '6c', '7h', '8s']], 1),
  ('lowest card trap', [['Ac', '5d', '6h', '7s'], ['2c', '3d', '4h', '8s']], 1),
  ('one-card hands', [['Ac', '2c', '3c', '4c'], ['5d', '6d', '7d', '8d']], 1),
  ('suit pair plus rank pair', [['2c', '2d', '5c', '9h'], ['3c', '4c', '6d', 'Th']], 1)],
 [('four-card badugi vs three', [['Ac', '2d', '3h', '4s'], ['Ac', '2c', '3h', '4s']], 1),
  ('paired rank different suits', [['Ac', 'Ad', '3h', '4s'], ['5c', '6d', '7h', 'Ks']], -1),
  ('lower badugi wins', [['Ac', '2d', '3h', '8s'], ['Ac', '2d', '4h', '7s']], -1),
  ('equal badugis', [['Ac', '2d', '3h', '4s'], ['Ad', '2c', '3s', '4h']], 0),
  ('best three-card subset', [['Kc', '2c', '3h', '4s'], ['5c', '6c', '7h', '8s']], 1),
  ('two-card hands', [['Ac', '2c', '3c', 'Kd'], ['4h', '5h', '6h', '7s']], -1),
  ('king high badugi vs three', [['Kc', 'Qd', 'Jh', 'Ts'], ['Ac', '2c', '3d', '4h']], 1),
  ('lowest card trap', [['Ac', '5d', '6h', '7s'], ['2c', '3d', '4h', '8s']], 1)],
 [('lower badugi wins', [['Ac', '2d', '3h', '8s'], ['Ac', '2d', '4h', '7s']], -1),
  ('equal badugis', [['Ac', '2d', '3h', '4s'], ['Ad', '2c', '3s', '4h']], 0),
  ('best three-card subset', [['Kc', '2c', '3h', '4s'], ['5c', '6c', '7h', '8s']], 1),
  ('two-card hands', [['Ac', '2c', '3c', 'Kd'], ['4h', '5h', '6h', '7s']], -1),
  ('king high badugi vs three', [['Kc', 'Qd', 'Jh', 'Ts'], ['Ac', '2c', '3d', '4h']], 1),
  ('lowest card trap', [['Ac', '5d', '6h', '7s'], ['2c', '3d', '4h', '8s']], 1),
  ('one-card hands', [['Ac', '2c', '3c', '4c'], ['5d', '6d', '7d', '8d']], 1),
  ('suit pair plus rank pair', [['2c', '2d', '5c', '9h'], ['3c', '4c', '6d', 'Th']], 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
four-card badugi vs three11Passed
paired rank different suits-1-1Passed
lower badugi wins-1-1Passed
equal badugis00Passed
best three-card subset11Passed
two-card hands-1-1Passed
king high badugi vs three11Passed
lowest card trap11Passed

SHA-256 / 71da7e9dfb5d7e3abb7b15c67d7eb5e93374c75e0697e454d947d69259de2d06

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

Case digest / 3adfa8cfc37207cb18d306a7cf020e86fb2ebdc42710527f00ccb11c95cbd983