FA-83761 / Card game rule engines / Open access
The royal marriage inside a run is scored twice · case 01
A trump run scores 190 instead of 150.
ROOT CAUSE
Marriages in trump are counted without removing those used by runs.
VERIFIED REPAIR
Subtract one royal marriage per run.
Unsuccessful approach: Removing only one marriage for a double run double-counts the second.
Case contract
Input [hand, trump]. Arounds (one of the rank in each suit): A 100, K 80, Q 60, J 40; double around x10. Run in trump (A T K Q J) 150 each; marriages (K+Q same suit) 20, royal marriage in trump 40, but a K+Q used in a run is not also a royal marriage. Pinochle (JD+QS) 40, double pinochle 300. Return the meld total.
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
from collections import Counter
N = 1
observations = []
def solve(x):
hand, trump = x
cnt = Counter(hand)
pts = 0
for r, v in (('A', 100), ('K', 80), ('Q', 60), ('J', 40)):
k = min(cnt[r + s] for s in 'SHDC')
if k >= 2:
pts += v * 10
elif k == 1:
pts += v
runs = min(cnt[r + trump] for r in 'ATKQJ')
pts += 150 * runs
for s in 'SHDC':
m = min(cnt['K' + s], cnt['Q' + s])
if s == trump:
pts += 40 * m
else:
pts += 20 * m
p = min(cnt['JD'], cnt['QS'])
pts += 300 if p == 2 else 40 * p
return pts
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[[[['AC', 'AC', 'AD', 'AD', 'AH', 'AH', 'AS', 'AS', 'JD', 'JD', 'QS', 'QS'], 'D'], 1300], [[['9C', '9D', '9S', 'AC', 'AH', 'JH', 'JS', 'KH', 'KH', 'KS', 'QH', 'TD'], 'C'], 20], [[['9D', 'JC', 'JD', 'JD', 'JH', 'KD', 'KS', 'QH', 'QS', 'QS', 'TC', 'TD'], 'H'], 320], [[['AC', 'AC', 'AD', 'AD', 'AH', 'AH', 'AS', 'AS', 'JD', 'JD', 'QS', 'QS'], 'D'], 1300], [[['9S', 'AH', 'AS', 'JC', 'JS', 'KD', 'KS', 'KS', 'QD', 'QS', 'TC', 'TS'], 'S'], 170], [[['AH', 'AH', 'AS', 'AS', 'JH', 'KC', 'KH', 'QH', 'QS', 'TH', 'TH', 'TS'], 'C'], 20], [[['9S', '9S', 'AC', 'JD', 'JD', 'KD', 'KS', 'QD', 'QS', 'QS', 'QS', 'TD'], 'D'], 360], [[['AD', 'AD', 'JD', 'JD', 'JH', 'JS', 'KD', 'KD', 'QD', 'QD', 'TD', 'TD'], 'D'], 300]], [[[['9D', '9H', '9S', 'AD', 'AH', 'JD', 'JS', 'KS', 'QS', 'TD', 'TS', 'TS'], 'C'], 60], [[['9C', 'AC', 'AC', 'AD', 'AH', 'AH', 'JD', 'JH', 'QC', 'QD', 'QH', 'TS'], 'C'], 0], [[['9C', '9D', '9S', 'AD', 'JH', 'JS', 'KC', 'QD', 'QH', 'TC', 'TD', 'TH'], 'D'], 0], [[['AC', 'AC', 'AD', 'AD', 'AH', 'AH', 'AS', 'AS', 'AS', 'QC', 'TC', 'TD'], 'H'], 1000], [[['9C', '9H', 'AC', 'AS', 'JC', 'KD', 'KH', 'QC', 'QH', 'TD', 'TH', 'TH'], 'S'], 20], [[['9D', '9S', 'AS', 'JC', 'JH', 'JS', 'KD', 'KH', 'KS', 'QC', 'QD', 'QS'], 'D'], 60], [[['AC', 'AC', 'JC', 'JD', 'JD', 'JD', 'KC', 'QC', 'QS', 'QS', 'TC', 'TC'], 'C'], 450], [[['AH', 'TH', 'KH', 'QH', 'JH', 'AH', 'TH', 'KH', 'QH', 'JH', '9S', '9D'], 'H'], 300]], [[[['9C', 'AS', 'JC', 'JH', 'KD', 'KD', 'KH', 'KS', 'QS', 'QS', 'TD', 'TH'], 'S'], 40], [[['AH', 'AH', 'JC', 'JH', 'JH', 'KH', 'KH', 'QH', 'QH', 'QS', 'TH', 'TH'], 'C'], 40], [[['AC', 'AC', 'AD', 'AD', 'AH', 'AH', 'AS', 'AS', 'JD', 'JD', 'QS', 'QS'], 'H'], 1300], [[['9C', '9D', 'AC', 'AD', 'AD', 'JD', 'JH', 'KD', 'KD', 'QD', 'QH', 'TD'], 'C'], 20], [[['9D', '9S', 'AD', 'JD', 'JD', 'KS', 'QD', 'QD', 'QH', 'QS', 'QS', 'TH'], 'S'], 340], [[['AC', 'AC', 'AC', 'AD', 'AD', 'AH', 'AH', 'AS', 'AS', 'KC', 'QC', 'TC'], 'D'], 1020], [[['9D', '9D', '9H', 'AC', 'JC', 'JH', 'KC', 'KS', 'QC', 'QD', 'TC', 'TH'], 'C'], 150], [[['AD', 'AD', 'AH', 'JC', 'JD', 'JD', 'KD', 'KD', 'QD', 'QD', 'TD', 'TD'], 'D'], 300]], [[[['9C', '9D', 'AC', 'AH', 'AH', 'KC', 'KD', 'KS', 'QC', 'QD', 'QS', 'TH'], 'H'], 60], [[['9C', '9C', 'AC', 'JD', 'KD', 'KD', 'KH', 'KS', 'QC', 'QH', 'TC', 'TD'], 'H'], 40], [[['9H', 'AC', 'AD', 'AS', 'JH', 'JS', 'KC', 'KD', 'QD', 'QH', 'TC', 'TD'], 'D'], 40], [[['AC', 'AC', 'AD', 'AD', 'AH', 'AH', 'AS', 'AS', 'JC', 'KS', 'QH', 'TS'], 'H'], 1000], [[['9C', '9D', '9D', '9H', 'AC', 'AH', 'JC', 'KC', 'KS', 'TC', 'TD', 'TH'], 'S'], 0], [[['AH', 'AH', 'JH', 'JH', 'JS', 'KH', 'KH', 'QH', 'QH', 'TD', 'TH', 'TH'], 'D'], 40], [[['AD', 'AD', 'JD', 'JD', 'JH', 'JS', 'KD', 'KD', 'QD', 'QD', 'TD', 'TD'], 'D'], 300], [[['AD', 'AS', 'JH', 'JS', 'JS', 'KS', 'KS', 'QD', 'QD', 'QS', 'TS', 'TS'], 'S'], 150]], [[[['9D', '9S', 'AH', 'JH', 'KC', 'KD', 'KS', 'QD', 'QD', 'TC', 'TC', 'TS'], 'D'], 40], [[['9D', 'AC', 'AH', 'JC', 'JH', 'JS', 'KC', 'KH', 'QC', 'TC', 'TH', 'TS'], 'S'], 20], [[['AC', 'AC', 'AD', 'AD', 'AH', 'AH', 'AS', 'AS', 'JD', 'JD', 'QS', 'QS'], 'S'], 1300], [[['AH', 'AH', 'JH', 'JH', 'KD', 'KD', 'KH', 'KH', 'QH', 'QH', 'TH', 'TH'], 'C'], 40], [[['9C', '9D', '9S', '9S', 'AD', 'AD', 'AH', 'AS', 'JC', 'JD', 'KH', 'QS'], 'C'], 40], [[['9C', '9H', 'AD', 'JC', 'JD', 'JS', 'JS', 'KC', 'KD', 'KH', 'TD', 'TH'], 'D'], 0], [[['9H', 'AC', 'AC', 'AD', 'AS', 'JC', 'KC', 'KD', 'QC', 'QD', 'TC', 'TS'], 'C'], 170], [[['AH', 'TH', 'KH', 'QH', 'JH', 'AH', 'TH', 'KH', 'QH', 'JH', '9S', '9D'], 'H'], 300]]]
for i, (args, expected) in enumerate(fixtures[N-1]):
check("meld points 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 points case 0 | 1300 | 1300 | Passed |
| meld points case 1 | 20 | 20 | Passed |
| meld points case 2 | 320 | 320 | Passed |
| meld points case 3 | 1300 | 1300 | Passed |
| meld points case 4 | 210 | 170 | Failed |
| meld points case 5 | 20 | 20 | Passed |
| meld points case 6 | 360 | 360 | Passed |
| meld points case 7 | 380 | 300 | Failed |
SHA-256 / 3e779543ba6ba4cbe7920884f926d35848bf8fc3eff8626f6557d428d4ab39b5
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
from collections import Counter
N = 1
observations = []
def solve(x):
hand, trump = x
cnt = Counter(hand)
pts = 0
for r, v in (('A', 100), ('K', 80), ('Q', 60), ('J', 40)):
k = min(cnt[r + s] for s in 'SHDC')
if k >= 2:
pts += v * 10
elif k == 1:
pts += v
runs = min(cnt[r + trump] for r in 'ATKQJ')
pts += 150 * runs
for s in 'SHDC':
m = min(cnt['K' + s], cnt['Q' + s])
if s == trump:
m -= 1 if runs else 0
pts += 40 * m
else:
pts += 20 * m
p = min(cnt['JD'], cnt['QS'])
pts += 300 if p == 2 else 40 * p
return pts
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[[[['AC', 'AC', 'AD', 'AD', 'AH', 'AH', 'AS', 'AS', 'JD', 'JD', 'QS', 'QS'], 'D'], 1300], [[['9C', '9D', '9S', 'AC', 'AH', 'JH', 'JS', 'KH', 'KH', 'KS', 'QH', 'TD'], 'C'], 20], [[['9D', 'JC', 'JD', 'JD', 'JH', 'KD', 'KS', 'QH', 'QS', 'QS', 'TC', 'TD'], 'H'], 320], [[['AC', 'AC', 'AD', 'AD', 'AH', 'AH', 'AS', 'AS', 'JD', 'JD', 'QS', 'QS'], 'D'], 1300], [[['9S', 'AH', 'AS', 'JC', 'JS', 'KD', 'KS', 'KS', 'QD', 'QS', 'TC', 'TS'], 'S'], 170], [[['AH', 'AH', 'AS', 'AS', 'JH', 'KC', 'KH', 'QH', 'QS', 'TH', 'TH', 'TS'], 'C'], 20], [[['9S', '9S', 'AC', 'JD', 'JD', 'KD', 'KS', 'QD', 'QS', 'QS', 'QS', 'TD'], 'D'], 360], [[['AD', 'AD', 'JD', 'JD', 'JH', 'JS', 'KD', 'KD', 'QD', 'QD', 'TD', 'TD'], 'D'], 300]], [[[['9D', '9H', '9S', 'AD', 'AH', 'JD', 'JS', 'KS', 'QS', 'TD', 'TS', 'TS'], 'C'], 60], [[['9C', 'AC', 'AC', 'AD', 'AH', 'AH', 'JD', 'JH', 'QC', 'QD', 'QH', 'TS'], 'C'], 0], [[['9C', '9D', '9S', 'AD', 'JH', 'JS', 'KC', 'QD', 'QH', 'TC', 'TD', 'TH'], 'D'], 0], [[['AC', 'AC', 'AD', 'AD', 'AH', 'AH', 'AS', 'AS', 'AS', 'QC', 'TC', 'TD'], 'H'], 1000], [[['9C', '9H', 'AC', 'AS', 'JC', 'KD', 'KH', 'QC', 'QH', 'TD', 'TH', 'TH'], 'S'], 20], [[['9D', '9S', 'AS', 'JC', 'JH', 'JS', 'KD', 'KH', 'KS', 'QC', 'QD', 'QS'], 'D'], 60], [[['AC', 'AC', 'JC', 'JD', 'JD', 'JD', 'KC', 'QC', 'QS', 'QS', 'TC', 'TC'], 'C'], 450], [[['AH', 'TH', 'KH', 'QH', 'JH', 'AH', 'TH', 'KH', 'QH', 'JH', '9S', '9D'], 'H'], 300]], [[[['9C', 'AS', 'JC', 'JH', 'KD', 'KD', 'KH', 'KS', 'QS', 'QS', 'TD', 'TH'], 'S'], 40], [[['AH', 'AH', 'JC', 'JH', 'JH', 'KH', 'KH', 'QH', 'QH', 'QS', 'TH', 'TH'], 'C'], 40], [[['AC', 'AC', 'AD', 'AD', 'AH', 'AH', 'AS', 'AS', 'JD', 'JD', 'QS', 'QS'], 'H'], 1300], [[['9C', '9D', 'AC', 'AD', 'AD', 'JD', 'JH', 'KD', 'KD', 'QD', 'QH', 'TD'], 'C'], 20], [[['9D', '9S', 'AD', 'JD', 'JD', 'KS', 'QD', 'QD', 'QH', 'QS', 'QS', 'TH'], 'S'], 340], [[['AC', 'AC', 'AC', 'AD', 'AD', 'AH', 'AH', 'AS', 'AS', 'KC', 'QC', 'TC'], 'D'], 1020], [[['9D', '9D', '9H', 'AC', 'JC', 'JH', 'KC', 'KS', 'QC', 'QD', 'TC', 'TH'], 'C'], 150], [[['AD', 'AD', 'AH', 'JC', 'JD', 'JD', 'KD', 'KD', 'QD', 'QD', 'TD', 'TD'], 'D'], 300]], [[[['9C', '9D', 'AC', 'AH', 'AH', 'KC', 'KD', 'KS', 'QC', 'QD', 'QS', 'TH'], 'H'], 60], [[['9C', '9C', 'AC', 'JD', 'KD', 'KD', 'KH', 'KS', 'QC', 'QH', 'TC', 'TD'], 'H'], 40], [[['9H', 'AC', 'AD', 'AS', 'JH', 'JS', 'KC', 'KD', 'QD', 'QH', 'TC', 'TD'], 'D'], 40], [[['AC', 'AC', 'AD', 'AD', 'AH', 'AH', 'AS', 'AS', 'JC', 'KS', 'QH', 'TS'], 'H'], 1000], [[['9C', '9D', '9D', '9H', 'AC', 'AH', 'JC', 'KC', 'KS', 'TC', 'TD', 'TH'], 'S'], 0], [[['AH', 'AH', 'JH', 'JH', 'JS', 'KH', 'KH', 'QH', 'QH', 'TD', 'TH', 'TH'], 'D'], 40], [[['AD', 'AD', 'JD', 'JD', 'JH', 'JS', 'KD', 'KD', 'QD', 'QD', 'TD', 'TD'], 'D'], 300], [[['AD', 'AS', 'JH', 'JS', 'JS', 'KS', 'KS', 'QD', 'QD', 'QS', 'TS', 'TS'], 'S'], 150]], [[[['9D', '9S', 'AH', 'JH', 'KC', 'KD', 'KS', 'QD', 'QD', 'TC', 'TC', 'TS'], 'D'], 40], [[['9D', 'AC', 'AH', 'JC', 'JH', 'JS', 'KC', 'KH', 'QC', 'TC', 'TH', 'TS'], 'S'], 20], [[['AC', 'AC', 'AD', 'AD', 'AH', 'AH', 'AS', 'AS', 'JD', 'JD', 'QS', 'QS'], 'S'], 1300], [[['AH', 'AH', 'JH', 'JH', 'KD', 'KD', 'KH', 'KH', 'QH', 'QH', 'TH', 'TH'], 'C'], 40], [[['9C', '9D', '9S', '9S', 'AD', 'AD', 'AH', 'AS', 'JC', 'JD', 'KH', 'QS'], 'C'], 40], [[['9C', '9H', 'AD', 'JC', 'JD', 'JS', 'JS', 'KC', 'KD', 'KH', 'TD', 'TH'], 'D'], 0], [[['9H', 'AC', 'AC', 'AD', 'AS', 'JC', 'KC', 'KD', 'QC', 'QD', 'TC', 'TS'], 'C'], 170], [[['AH', 'TH', 'KH', 'QH', 'JH', 'AH', 'TH', 'KH', 'QH', 'JH', '9S', '9D'], 'H'], 300]]]
for i, (args, expected) in enumerate(fixtures[N-1]):
check("meld points 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 points case 0 | 1300 | 1300 | Passed |
| meld points case 1 | 20 | 20 | Passed |
| meld points case 2 | 320 | 320 | Passed |
| meld points case 3 | 1300 | 1300 | Passed |
| meld points case 4 | 170 | 170 | Passed |
| meld points case 5 | 20 | 20 | Passed |
| meld points case 6 | 360 | 360 | Passed |
| meld points case 7 | 340 | 300 | Failed |
SHA-256 / 5987e73b213ccba209adf85be84f7308e7e9bd0936daa042bed73e1c2ae914c6
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
from collections import Counter
N = 1
observations = []
def solve(x):
hand, trump = x
cnt = Counter(hand)
pts = 0
for r, v in (('A', 100), ('K', 80), ('Q', 60), ('J', 40)):
k = min(cnt[r + s] for s in 'SHDC')
if k >= 2:
pts += v * 10
elif k == 1:
pts += v
runs = min(cnt[r + trump] for r in 'ATKQJ')
pts += 150 * runs
for s in 'SHDC':
m = min(cnt['K' + s], cnt['Q' + s])
if s == trump:
m -= runs
pts += 40 * m
else:
pts += 20 * m
p = min(cnt['JD'], cnt['QS'])
pts += 300 if p == 2 else 40 * p
return pts
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[[[['AC', 'AC', 'AD', 'AD', 'AH', 'AH', 'AS', 'AS', 'JD', 'JD', 'QS', 'QS'], 'D'], 1300], [[['9C', '9D', '9S', 'AC', 'AH', 'JH', 'JS', 'KH', 'KH', 'KS', 'QH', 'TD'], 'C'], 20], [[['9D', 'JC', 'JD', 'JD', 'JH', 'KD', 'KS', 'QH', 'QS', 'QS', 'TC', 'TD'], 'H'], 320], [[['AC', 'AC', 'AD', 'AD', 'AH', 'AH', 'AS', 'AS', 'JD', 'JD', 'QS', 'QS'], 'D'], 1300], [[['9S', 'AH', 'AS', 'JC', 'JS', 'KD', 'KS', 'KS', 'QD', 'QS', 'TC', 'TS'], 'S'], 170], [[['AH', 'AH', 'AS', 'AS', 'JH', 'KC', 'KH', 'QH', 'QS', 'TH', 'TH', 'TS'], 'C'], 20], [[['9S', '9S', 'AC', 'JD', 'JD', 'KD', 'KS', 'QD', 'QS', 'QS', 'QS', 'TD'], 'D'], 360], [[['AD', 'AD', 'JD', 'JD', 'JH', 'JS', 'KD', 'KD', 'QD', 'QD', 'TD', 'TD'], 'D'], 300]], [[[['9D', '9H', '9S', 'AD', 'AH', 'JD', 'JS', 'KS', 'QS', 'TD', 'TS', 'TS'], 'C'], 60], [[['9C', 'AC', 'AC', 'AD', 'AH', 'AH', 'JD', 'JH', 'QC', 'QD', 'QH', 'TS'], 'C'], 0], [[['9C', '9D', '9S', 'AD', 'JH', 'JS', 'KC', 'QD', 'QH', 'TC', 'TD', 'TH'], 'D'], 0], [[['AC', 'AC', 'AD', 'AD', 'AH', 'AH', 'AS', 'AS', 'AS', 'QC', 'TC', 'TD'], 'H'], 1000], [[['9C', '9H', 'AC', 'AS', 'JC', 'KD', 'KH', 'QC', 'QH', 'TD', 'TH', 'TH'], 'S'], 20], [[['9D', '9S', 'AS', 'JC', 'JH', 'JS', 'KD', 'KH', 'KS', 'QC', 'QD', 'QS'], 'D'], 60], [[['AC', 'AC', 'JC', 'JD', 'JD', 'JD', 'KC', 'QC', 'QS', 'QS', 'TC', 'TC'], 'C'], 450], [[['AH', 'TH', 'KH', 'QH', 'JH', 'AH', 'TH', 'KH', 'QH', 'JH', '9S', '9D'], 'H'], 300]], [[[['9C', 'AS', 'JC', 'JH', 'KD', 'KD', 'KH', 'KS', 'QS', 'QS', 'TD', 'TH'], 'S'], 40], [[['AH', 'AH', 'JC', 'JH', 'JH', 'KH', 'KH', 'QH', 'QH', 'QS', 'TH', 'TH'], 'C'], 40], [[['AC', 'AC', 'AD', 'AD', 'AH', 'AH', 'AS', 'AS', 'JD', 'JD', 'QS', 'QS'], 'H'], 1300], [[['9C', '9D', 'AC', 'AD', 'AD', 'JD', 'JH', 'KD', 'KD', 'QD', 'QH', 'TD'], 'C'], 20], [[['9D', '9S', 'AD', 'JD', 'JD', 'KS', 'QD', 'QD', 'QH', 'QS', 'QS', 'TH'], 'S'], 340], [[['AC', 'AC', 'AC', 'AD', 'AD', 'AH', 'AH', 'AS', 'AS', 'KC', 'QC', 'TC'], 'D'], 1020], [[['9D', '9D', '9H', 'AC', 'JC', 'JH', 'KC', 'KS', 'QC', 'QD', 'TC', 'TH'], 'C'], 150], [[['AD', 'AD', 'AH', 'JC', 'JD', 'JD', 'KD', 'KD', 'QD', 'QD', 'TD', 'TD'], 'D'], 300]], [[[['9C', '9D', 'AC', 'AH', 'AH', 'KC', 'KD', 'KS', 'QC', 'QD', 'QS', 'TH'], 'H'], 60], [[['9C', '9C', 'AC', 'JD', 'KD', 'KD', 'KH', 'KS', 'QC', 'QH', 'TC', 'TD'], 'H'], 40], [[['9H', 'AC', 'AD', 'AS', 'JH', 'JS', 'KC', 'KD', 'QD', 'QH', 'TC', 'TD'], 'D'], 40], [[['AC', 'AC', 'AD', 'AD', 'AH', 'AH', 'AS', 'AS', 'JC', 'KS', 'QH', 'TS'], 'H'], 1000], [[['9C', '9D', '9D', '9H', 'AC', 'AH', 'JC', 'KC', 'KS', 'TC', 'TD', 'TH'], 'S'], 0], [[['AH', 'AH', 'JH', 'JH', 'JS', 'KH', 'KH', 'QH', 'QH', 'TD', 'TH', 'TH'], 'D'], 40], [[['AD', 'AD', 'JD', 'JD', 'JH', 'JS', 'KD', 'KD', 'QD', 'QD', 'TD', 'TD'], 'D'], 300], [[['AD', 'AS', 'JH', 'JS', 'JS', 'KS', 'KS', 'QD', 'QD', 'QS', 'TS', 'TS'], 'S'], 150]], [[[['9D', '9S', 'AH', 'JH', 'KC', 'KD', 'KS', 'QD', 'QD', 'TC', 'TC', 'TS'], 'D'], 40], [[['9D', 'AC', 'AH', 'JC', 'JH', 'JS', 'KC', 'KH', 'QC', 'TC', 'TH', 'TS'], 'S'], 20], [[['AC', 'AC', 'AD', 'AD', 'AH', 'AH', 'AS', 'AS', 'JD', 'JD', 'QS', 'QS'], 'S'], 1300], [[['AH', 'AH', 'JH', 'JH', 'KD', 'KD', 'KH', 'KH', 'QH', 'QH', 'TH', 'TH'], 'C'], 40], [[['9C', '9D', '9S', '9S', 'AD', 'AD', 'AH', 'AS', 'JC', 'JD', 'KH', 'QS'], 'C'], 40], [[['9C', '9H', 'AD', 'JC', 'JD', 'JS', 'JS', 'KC', 'KD', 'KH', 'TD', 'TH'], 'D'], 0], [[['9H', 'AC', 'AC', 'AD', 'AS', 'JC', 'KC', 'KD', 'QC', 'QD', 'TC', 'TS'], 'C'], 170], [[['AH', 'TH', 'KH', 'QH', 'JH', 'AH', 'TH', 'KH', 'QH', 'JH', '9S', '9D'], 'H'], 300]]]
for i, (args, expected) in enumerate(fixtures[N-1]):
check("meld points 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 points case 0 | 1300 | 1300 | Passed |
| meld points case 1 | 20 | 20 | Passed |
| meld points case 2 | 320 | 320 | Passed |
| meld points case 3 | 1300 | 1300 | Passed |
| meld points case 4 | 170 | 170 | Passed |
| meld points case 5 | 20 | 20 | Passed |
| meld points case 6 | 360 | 360 | Passed |
| meld points case 7 | 300 | 300 | Passed |
SHA-256 / 9da4cc983f65c36bebec48fcced43e0f1cdd61b65e74b4439ef72182a2255a13
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:24.582029+00:00.
Case digest / 517727dcc2305a0cb72c4e9aea5a0e5ec9a05581b76b2f664e85b1a9ecc0ab1d