FA-83461 / Card game rule engines / Open access
Sets with a repeated suit are accepted · case 01
Two copies of the nine of clubs plus another nine form a "set".
ROOT CAUSE
The set test only checks the rank and size.
VERIFIED REPAIR
Every card in a set must have a different suit.
Unsuccessful approach: Tolerating one repeated suit still accepts duplicated cards.
Case contract
Input a list of cards. A set is 3-4 cards of one rank in distinct suits. A run is 3+ consecutive cards of one suit; ace is low (A-2-3) or high (Q-K-A) but runs do not wrap (K-A-2). Return "set", "run" or "invalid".
Why this case matters
Card-game engines, scoring apps and online tables apply this rule automatically on every hand.
1 / The failure
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(x):
cards = x
order = 'A23456789TJQK'
if len(cards) < 3:
return 'invalid'
ranks = [c[0] for c in cards]
suits = [c[1] for c in cards]
if len(set(ranks)) == 1:
if len(cards) <= 4:
return 'set'
return 'invalid'
if len(set(suits)) != 1:
return 'invalid'
idx = sorted(order.index(r) for r in ranks)
if all(idx[i + 1] == idx[i] + 1 for i in range(len(idx) - 1)):
return 'run'
if idx[0] == 0:
high = sorted(idx[1:] + [13])
if all(high[i + 1] == high[i] + 1 for i in range(len(high) - 1)):
return 'run'
return 'invalid'
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[[['9H', '9C', '9D', '9D'], 'invalid'], [['4D', '5D', '3D', '6D'], 'run'], [['KD', '6S', 'QS', '6H'], 'invalid'], [['8H', '8S'], 'invalid'], [['JD', 'QD', '2D', 'KD', 'AD'], 'invalid'], [['8H', '6D', 'AH'], 'invalid'], [['4S', '4H', '4D'], 'set'], [['JH', 'JH', 'JC'], 'invalid']], [[['9C', 'JC', 'QC', 'TC'], 'run'], [['7S', '4D', 'JC'], 'invalid'], [['KH', 'QH', 'JH'], 'run'], [['5D', '5S'], 'invalid'], [['KD', 'TD', 'AD', 'JD', 'QD'], 'run'], [['KH', 'KD', 'KC', 'KC', 'KS'], 'invalid'], [['2H', '2H', '2S'], 'invalid'], [['JC', 'JH', 'JH'], 'invalid']], [[['JH', '9H', 'TH'], 'run'], [['TH', 'KH', 'QH', 'JH'], 'run'], [['6C', '2C', '8D', '8C'], 'invalid'], [['5H', '2H', '3H', '6H', '4H'], 'run'], [['4H', '4S', '4C', '4D'], 'set'], [['3D', '3H', '3C'], 'set'], [['JH', 'JH', 'JC'], 'invalid'], [['9C', '9H', '9D', '9C'], 'invalid']], [[['AD', 'AH', 'AD'], 'invalid'], [['QC', 'QS', 'QD', 'QD'], 'invalid'], [['9S', 'JS', 'QS', '8S', 'TS'], 'run'], [['KS', '4S', '8D', '3C'], 'invalid'], [['9C', 'JC', 'TC', '8C'], 'run'], [['AH', '2H', '3H'], 'run'], [['6H', '6S', '6H'], 'invalid'], [['4C', '4H', '4C', '4D'], 'invalid']], [[['9C', '3S', '3H'], 'invalid'], [['9H', 'JH', 'QC', '2D'], 'invalid'], [['5S', 'AH'], 'invalid'], [['TH', 'JH', 'KH', 'QH'], 'run'], [['QC', '6D'], 'invalid'], [['9D', '7D', '3S', '9S'], 'invalid'], [['4C', '4H', '4C', '4D'], 'invalid'], [['2S', '2S', '2H'], 'invalid']]]
for i, (args, expected) in enumerate(fixtures[N-1]):
check("meld case %d" % i, solve(args), 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 |
|---|---|---|---|
| meld case 0 | set | invalid | Failed |
| meld case 1 | run | run | Passed |
| meld case 2 | invalid | invalid | Passed |
| meld case 3 | invalid | invalid | Passed |
| meld case 4 | invalid | invalid | Passed |
| meld case 5 | invalid | invalid | Passed |
| meld case 6 | set | set | Passed |
| meld case 7 | set | invalid | Failed |
SHA-256 / 65553c6350ac2761ec12e6e070feee26082768a2ce3acfec5e9df025ef91eeab
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(x):
cards = x
order = 'A23456789TJQK'
if len(cards) < 3:
return 'invalid'
ranks = [c[0] for c in cards]
suits = [c[1] for c in cards]
if len(set(ranks)) == 1:
if len(cards) <= 4 and len(set(suits)) >= len(cards) - 1:
return 'set'
return 'invalid'
if len(set(suits)) != 1:
return 'invalid'
idx = sorted(order.index(r) for r in ranks)
if all(idx[i + 1] == idx[i] + 1 for i in range(len(idx) - 1)):
return 'run'
if idx[0] == 0:
high = sorted(idx[1:] + [13])
if all(high[i + 1] == high[i] + 1 for i in range(len(high) - 1)):
return 'run'
return 'invalid'
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[[['9H', '9C', '9D', '9D'], 'invalid'], [['4D', '5D', '3D', '6D'], 'run'], [['KD', '6S', 'QS', '6H'], 'invalid'], [['8H', '8S'], 'invalid'], [['JD', 'QD', '2D', 'KD', 'AD'], 'invalid'], [['8H', '6D', 'AH'], 'invalid'], [['4S', '4H', '4D'], 'set'], [['JH', 'JH', 'JC'], 'invalid']], [[['9C', 'JC', 'QC', 'TC'], 'run'], [['7S', '4D', 'JC'], 'invalid'], [['KH', 'QH', 'JH'], 'run'], [['5D', '5S'], 'invalid'], [['KD', 'TD', 'AD', 'JD', 'QD'], 'run'], [['KH', 'KD', 'KC', 'KC', 'KS'], 'invalid'], [['2H', '2H', '2S'], 'invalid'], [['JC', 'JH', 'JH'], 'invalid']], [[['JH', '9H', 'TH'], 'run'], [['TH', 'KH', 'QH', 'JH'], 'run'], [['6C', '2C', '8D', '8C'], 'invalid'], [['5H', '2H', '3H', '6H', '4H'], 'run'], [['4H', '4S', '4C', '4D'], 'set'], [['3D', '3H', '3C'], 'set'], [['JH', 'JH', 'JC'], 'invalid'], [['9C', '9H', '9D', '9C'], 'invalid']], [[['AD', 'AH', 'AD'], 'invalid'], [['QC', 'QS', 'QD', 'QD'], 'invalid'], [['9S', 'JS', 'QS', '8S', 'TS'], 'run'], [['KS', '4S', '8D', '3C'], 'invalid'], [['9C', 'JC', 'TC', '8C'], 'run'], [['AH', '2H', '3H'], 'run'], [['6H', '6S', '6H'], 'invalid'], [['4C', '4H', '4C', '4D'], 'invalid']], [[['9C', '3S', '3H'], 'invalid'], [['9H', 'JH', 'QC', '2D'], 'invalid'], [['5S', 'AH'], 'invalid'], [['TH', 'JH', 'KH', 'QH'], 'run'], [['QC', '6D'], 'invalid'], [['9D', '7D', '3S', '9S'], 'invalid'], [['4C', '4H', '4C', '4D'], 'invalid'], [['2S', '2S', '2H'], 'invalid']]]
for i, (args, expected) in enumerate(fixtures[N-1]):
check("meld case %d" % i, solve(args), 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 |
|---|---|---|---|
| meld case 0 | set | invalid | Failed |
| meld case 1 | run | run | Passed |
| meld case 2 | invalid | invalid | Passed |
| meld case 3 | invalid | invalid | Passed |
| meld case 4 | invalid | invalid | Passed |
| meld case 5 | invalid | invalid | Passed |
| meld case 6 | set | set | Passed |
| meld case 7 | set | invalid | Failed |
SHA-256 / d84fc7e0913a2e21447c2348c1b4b6341bbaa3cfae975dc94e770f50f6727d56
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(x):
cards = x
order = 'A23456789TJQK'
if len(cards) < 3:
return 'invalid'
ranks = [c[0] for c in cards]
suits = [c[1] for c in cards]
if len(set(ranks)) == 1:
if len(cards) <= 4 and len(set(suits)) == len(cards):
return 'set'
return 'invalid'
if len(set(suits)) != 1:
return 'invalid'
idx = sorted(order.index(r) for r in ranks)
if all(idx[i + 1] == idx[i] + 1 for i in range(len(idx) - 1)):
return 'run'
if idx[0] == 0:
high = sorted(idx[1:] + [13])
if all(high[i + 1] == high[i] + 1 for i in range(len(high) - 1)):
return 'run'
return 'invalid'
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[[['9H', '9C', '9D', '9D'], 'invalid'], [['4D', '5D', '3D', '6D'], 'run'], [['KD', '6S', 'QS', '6H'], 'invalid'], [['8H', '8S'], 'invalid'], [['JD', 'QD', '2D', 'KD', 'AD'], 'invalid'], [['8H', '6D', 'AH'], 'invalid'], [['4S', '4H', '4D'], 'set'], [['JH', 'JH', 'JC'], 'invalid']], [[['9C', 'JC', 'QC', 'TC'], 'run'], [['7S', '4D', 'JC'], 'invalid'], [['KH', 'QH', 'JH'], 'run'], [['5D', '5S'], 'invalid'], [['KD', 'TD', 'AD', 'JD', 'QD'], 'run'], [['KH', 'KD', 'KC', 'KC', 'KS'], 'invalid'], [['2H', '2H', '2S'], 'invalid'], [['JC', 'JH', 'JH'], 'invalid']], [[['JH', '9H', 'TH'], 'run'], [['TH', 'KH', 'QH', 'JH'], 'run'], [['6C', '2C', '8D', '8C'], 'invalid'], [['5H', '2H', '3H', '6H', '4H'], 'run'], [['4H', '4S', '4C', '4D'], 'set'], [['3D', '3H', '3C'], 'set'], [['JH', 'JH', 'JC'], 'invalid'], [['9C', '9H', '9D', '9C'], 'invalid']], [[['AD', 'AH', 'AD'], 'invalid'], [['QC', 'QS', 'QD', 'QD'], 'invalid'], [['9S', 'JS', 'QS', '8S', 'TS'], 'run'], [['KS', '4S', '8D', '3C'], 'invalid'], [['9C', 'JC', 'TC', '8C'], 'run'], [['AH', '2H', '3H'], 'run'], [['6H', '6S', '6H'], 'invalid'], [['4C', '4H', '4C', '4D'], 'invalid']], [[['9C', '3S', '3H'], 'invalid'], [['9H', 'JH', 'QC', '2D'], 'invalid'], [['5S', 'AH'], 'invalid'], [['TH', 'JH', 'KH', 'QH'], 'run'], [['QC', '6D'], 'invalid'], [['9D', '7D', '3S', '9S'], 'invalid'], [['4C', '4H', '4C', '4D'], 'invalid'], [['2S', '2S', '2H'], 'invalid']]]
for i, (args, expected) in enumerate(fixtures[N-1]):
check("meld case %d" % i, solve(args), 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 |
|---|---|---|---|
| meld case 0 | invalid | invalid | Passed |
| meld case 1 | run | run | Passed |
| meld case 2 | invalid | invalid | Passed |
| meld case 3 | invalid | invalid | Passed |
| meld case 4 | invalid | invalid | Passed |
| meld case 5 | invalid | invalid | Passed |
| meld case 6 | set | set | Passed |
| meld case 7 | invalid | invalid | Passed |
SHA-256 / f98848a41083f57b8105da465d71e81ca1086bf9be46a3b91a9c2a10bb7432d0
Verification & scope
A bounded toy rule contract stated explicitly in the contract field; cards are two-character codes (rank, suit). Not a complete implementation of any published rulebook or casino table rules. 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:21.912015+00:00.
Case digest / d0c6f40ad3712065e989061d637eb81651c7bba6a8f586c05382cb2cdb196843