FAILURE MAP
← Case archive

FA-83776 / Card game rule engines / Open access

Trump marriages score like plain marriages · case 01

A royal marriage scores 20.

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

ROOT CAUSE

The trump branch uses the plain value.

VERIFIED REPAIR

Royal marriages are 40.

Unsuccessful approach: Paying 40 only for the first royal marriage underpays a second one.

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:
            m -= runs
            pts += 20 * 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 = [[[[['9C', '9D', '9D', 'AD', 'AD', 'AS', 'JC', 'JD', 'KD', 'KH', 'QC', 'QH'], 'H'], 40], [[['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], [[['KH', 'QH', 'KH', 'QH', '9S', '9D', 'AC', 'TC', 'JS', 'JC', '9C', 'TD'], 'H'], 80]], [[[['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], [[['9C', 'AS', 'JC', 'JH', 'KD', 'KD', 'KH', 'KS', 'QS', 'QS', 'TD', 'TH'], 'S'], 40], [[['KS', 'QS', 'KS', 'QS', 'KD', 'QD', 'AC', 'TC', 'JH', 'JC', '9C', 'TH'], 'S'], 100]], [[[['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], [[['9H', 'AC', 'AD', 'AS', 'JH', 'JS', 'KC', 'KD', 'QD', 'QH', 'TC', 'TD'], 'D'], 40], [[['KH', 'QH', 'KH', 'QH', '9S', '9D', 'AC', 'TC', 'JS', 'JC', '9C', 'TD'], 'H'], 80]], [[[['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], [[['9S', 'AC', 'JC', 'KC', 'KD', 'KS', 'QC', 'QC', 'QD', 'QS', 'TC', 'TD'], 'S'], 80], [[['KS', 'QS', 'KS', 'QS', 'KD', 'QD', 'AC', 'TC', 'JH', 'JC', '9C', 'TH'], 'S'], 100]], [[[['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', 'JC', 'JD', 'JS', 'JS', 'KC', 'KD', 'KD', 'KH', 'QD', 'QH', 'TD'], 'D'], 60], [[['KH', 'QH', 'KH', 'QH', '9S', '9D', 'AC', 'TC', 'JS', 'JC', '9C', 'TD'], 'H'], 80]]]
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 fixtureActualExpectedOutcome
meld points case 02040Failed
meld points case 12020Passed
meld points case 2320320Passed
meld points case 313001300Passed
meld points case 4170170Passed
meld points case 52020Passed
meld points case 6340360Failed
meld points case 74080Failed

SHA-256 / 167603e11954ddf028b1ae3899e813ced54777bf16bf074e2495a59d4ceafe59

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 -= runs
            pts += 40 * min(m, 1) + 20 * max(m - 1, 0)
        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 = [[[[['9C', '9D', '9D', 'AD', 'AD', 'AS', 'JC', 'JD', 'KD', 'KH', 'QC', 'QH'], 'H'], 40], [[['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], [[['KH', 'QH', 'KH', 'QH', '9S', '9D', 'AC', 'TC', 'JS', 'JC', '9C', 'TD'], 'H'], 80]], [[[['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], [[['9C', 'AS', 'JC', 'JH', 'KD', 'KD', 'KH', 'KS', 'QS', 'QS', 'TD', 'TH'], 'S'], 40], [[['KS', 'QS', 'KS', 'QS', 'KD', 'QD', 'AC', 'TC', 'JH', 'JC', '9C', 'TH'], 'S'], 100]], [[[['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], [[['9H', 'AC', 'AD', 'AS', 'JH', 'JS', 'KC', 'KD', 'QD', 'QH', 'TC', 'TD'], 'D'], 40], [[['KH', 'QH', 'KH', 'QH', '9S', '9D', 'AC', 'TC', 'JS', 'JC', '9C', 'TD'], 'H'], 80]], [[[['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], [[['9S', 'AC', 'JC', 'KC', 'KD', 'KS', 'QC', 'QC', 'QD', 'QS', 'TC', 'TD'], 'S'], 80], [[['KS', 'QS', 'KS', 'QS', 'KD', 'QD', 'AC', 'TC', 'JH', 'JC', '9C', 'TH'], 'S'], 100]], [[[['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', 'JC', 'JD', 'JS', 'JS', 'KC', 'KD', 'KD', 'KH', 'QD', 'QH', 'TD'], 'D'], 60], [[['KH', 'QH', 'KH', 'QH', '9S', '9D', 'AC', 'TC', 'JS', 'JC', '9C', 'TD'], 'H'], 80]]]
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 fixtureActualExpectedOutcome
meld points case 04040Passed
meld points case 12020Passed
meld points case 2320320Passed
meld points case 313001300Passed
meld points case 4170170Passed
meld points case 52020Passed
meld points case 6360360Passed
meld points case 76080Failed

SHA-256 / 3ceca41da24dc286b8ee307ae1899cae449b8e65f4f7b0d3e3526ed6e1fcbaa7

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 = [[[[['9C', '9D', '9D', 'AD', 'AD', 'AS', 'JC', 'JD', 'KD', 'KH', 'QC', 'QH'], 'H'], 40], [[['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], [[['KH', 'QH', 'KH', 'QH', '9S', '9D', 'AC', 'TC', 'JS', 'JC', '9C', 'TD'], 'H'], 80]], [[[['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], [[['9C', 'AS', 'JC', 'JH', 'KD', 'KD', 'KH', 'KS', 'QS', 'QS', 'TD', 'TH'], 'S'], 40], [[['KS', 'QS', 'KS', 'QS', 'KD', 'QD', 'AC', 'TC', 'JH', 'JC', '9C', 'TH'], 'S'], 100]], [[[['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], [[['9H', 'AC', 'AD', 'AS', 'JH', 'JS', 'KC', 'KD', 'QD', 'QH', 'TC', 'TD'], 'D'], 40], [[['KH', 'QH', 'KH', 'QH', '9S', '9D', 'AC', 'TC', 'JS', 'JC', '9C', 'TD'], 'H'], 80]], [[[['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], [[['9S', 'AC', 'JC', 'KC', 'KD', 'KS', 'QC', 'QC', 'QD', 'QS', 'TC', 'TD'], 'S'], 80], [[['KS', 'QS', 'KS', 'QS', 'KD', 'QD', 'AC', 'TC', 'JH', 'JC', '9C', 'TH'], 'S'], 100]], [[[['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', 'JC', 'JD', 'JS', 'JS', 'KC', 'KD', 'KD', 'KH', 'QD', 'QH', 'TD'], 'D'], 60], [[['KH', 'QH', 'KH', 'QH', '9S', '9D', 'AC', 'TC', 'JS', 'JC', '9C', 'TD'], 'H'], 80]]]
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 fixtureActualExpectedOutcome
meld points case 04040Passed
meld points case 12020Passed
meld points case 2320320Passed
meld points case 313001300Passed
meld points case 4170170Passed
meld points case 52020Passed
meld points case 6360360Passed
meld points case 78080Passed

SHA-256 / 64d198551150f9a45ffffa6f9ae011f3eac8ad985ae16c5122b647769c187472

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

Case digest / 33511a3a8541a5af7ebad10fb6d0bed3b8f0812737df2fcd5851e94e89c997f6