{"abstract":"\"A9s-A6s\" counts three classes instead of four.","category":"Poker hand evaluation","checks":8,"contract":"Input: a comma-separated hold'em range string. Tokens: pairs \"77\", \"77+\" (up to AA), \"TT-77\"; non-pairs \"AKs\"/\"AKo\"/\"AK\" (no suffix means both suited and offsuit), \"A9s+\" (kicker rises to one below the top card), \"A9s-A6s\" (inclusive). Whitespace around tokens is ignored. Duplicated classes count once. Return total combos: pair 6, suited 4, offsuit 12.","evaluation_group":"w2-poker_hand_evaluation-range-combo-count","failed_approach":"Shifting the start instead drops the lower named kicker.","family":"w2-poker_hand_evaluation-range-combo-count-dash-range-inclusivity","id":"FA-82131","implementations":{"attempt":{"sha256":"5b5156da50301e7b5ac6724d384f57ec49412b4f7ae1fb4bb61bacff0836f8d4","source":"\"\"\"Failure Map reference implementation. Python standard library only.\"\"\"\nimport json\n\nN = 1\nobservations = []\ndef solve(x):\n    R='23456789TJQKA'\n    classes=set()\n    def add(h, suf):\n        if h[0]==h[1]: classes.add(h)\n        elif suf: classes.add(h+suf)\n        else:\n            classes.add(h+'s'); classes.add(h+'o')\n    for tok in x.split(','):\n        tok=tok.strip()\n        if not tok: continue\n        plus=tok.endswith('+')\n        t=tok.rstrip('+')\n        if '-' in t:\n            a,b=t.split('-')\n            if a[0]==a[1]:\n                lo,hi=sorted([R.index(a[0]),R.index(b[0])])\n                for i in range(lo,hi+1): add(R[i]*2,'')\n            else:\n                lo,hi=sorted([R.index(a[1]),R.index(b[1])])\n                for i in range(lo+1,hi+1): add(a[0]+R[i],a[2:])\n            continue\n        if t[0]==t[1]:\n            start=R.index(t[0])\n            stop=len(R)-1 if plus else start\n            for i in range(start,stop+1): add(R[i]*2,'')\n        else:\n            top=R.index(t[0]); k=R.index(t[1])\n            stop=top-1 if plus else k\n            for i in range(k,stop+1): add(t[0]+R[i],t[2:])\n    total=0\n    for c in classes:\n        if c[0]==c[1]: total+=6\n        elif c.endswith('s'): total+=4\n        else: total+=12\n    return total\ndef check(label, actual, expected):\n    observations.append({\"check\": label, \"actual\": actual, \"expected\": expected, \"passed\": actual == expected})\nfixtures = [[('pairs plus', '77+', 48), ('queens plus', 'QQ+', 18), ('suited ace plus', 'A9s+', 20),\n  ('offsuit king plus', 'KTo+', 36), ('unsuffixed class', 'AK', 16),\n  ('dash kicker range', 'A9s-A6s', 16), ('dash pair range', 'TT-77', 24),\n  ('reversed kicker dash', 'K6o-K9o', 48)],\n [('offsuit king plus', 'KTo+', 36), ('unsuffixed class', 'AK', 16),\n  ('dash kicker range', 'A9s-A6s', 16), ('dash pair range', 'TT-77', 24),\n  ('reversed dash pairs', '77-TT', 24), ('spaced tokens', 'QQ+, AKs', 22),\n  ('overlap dedupe', 'AKs,AK', 16), ('reversed kicker dash', 'K6o-K9o', 48)],\n [('dash kicker range', 'A9s-A6s', 16), ('reversed dash pairs', '77-TT', 24),\n  ('spaced tokens', 'QQ+, AKs', 22), ('overlap dedupe', 'AKs,AK', 16), ('single pair', '22', 6),\n  ('mixed', 'JJ+,AQs+,KQo', 44), ('aces only', 'AA', 6), ('reversed kicker dash', 'K6o-K9o', 48)],\n [('pairs plus', '77+', 48), ('dash kicker range', 'A9s-A6s', 16), ('single pair', '22', 6),\n  ('mixed', 'JJ+,AQs+,KQo', 44), ('aces only', 'AA', 6), ('suited connector plus', 'T9s+', 4),\n  ('trailing comma', 'KK+,', 12), ('reversed kicker dash', 'K6o-K9o', 48)],\n [('pairs plus', '77+', 48), ('queens plus', 'QQ+', 18), ('suited ace plus', 'A9s+', 20),\n  ('offsuit king plus', 'KTo+', 36), ('dash kicker range', 'A9s-A6s', 16),\n  ('suited connector plus', 'T9s+', 4), ('trailing comma', 'KK+,', 12),\n  ('reversed kicker dash', 'K6o-K9o', 48)]]\nfor label, args, expected in fixtures[N-1]:\n    try:\n        actual = solve(args)\n    except Exception as exc:\n        actual = 'error:' + type(exc).__name__\n    check(label, actual, expected)\nprint(json.dumps({\"observations\": observations, \"passed\": all(x[\"passed\"] for x in observations)}, ensure_ascii=False))\nraise SystemExit(0 if all(x[\"passed\"] for x in observations) else 1)\n"},"broken":{"sha256":"a127492b7f267bf73dc3bcf9d5d361306623b039afda62977f2b221719d1dd7f","source":"\"\"\"Failure Map reference implementation. Python standard library only.\"\"\"\nimport json\n\nN = 1\nobservations = []\ndef solve(x):\n    R='23456789TJQKA'\n    classes=set()\n    def add(h, suf):\n        if h[0]==h[1]: classes.add(h)\n        elif suf: classes.add(h+suf)\n        else:\n            classes.add(h+'s'); classes.add(h+'o')\n    for tok in x.split(','):\n        tok=tok.strip()\n        if not tok: continue\n        plus=tok.endswith('+')\n        t=tok.rstrip('+')\n        if '-' in t:\n            a,b=t.split('-')\n            if a[0]==a[1]:\n                lo,hi=sorted([R.index(a[0]),R.index(b[0])])\n                for i in range(lo,hi+1): add(R[i]*2,'')\n            else:\n                lo,hi=sorted([R.index(a[1]),R.index(b[1])])\n                for i in range(lo,hi): add(a[0]+R[i],a[2:])\n            continue\n        if t[0]==t[1]:\n            start=R.index(t[0])\n            stop=len(R)-1 if plus else start\n            for i in range(start,stop+1): add(R[i]*2,'')\n        else:\n            top=R.index(t[0]); k=R.index(t[1])\n            stop=top-1 if plus else k\n            for i in range(k,stop+1): add(t[0]+R[i],t[2:])\n    total=0\n    for c in classes:\n        if c[0]==c[1]: total+=6\n        elif c.endswith('s'): total+=4\n        else: total+=12\n    return total\ndef check(label, actual, expected):\n    observations.append({\"check\": label, \"actual\": actual, \"expected\": expected, \"passed\": actual == expected})\nfixtures = [[('pairs plus', '77+', 48), ('queens plus', 'QQ+', 18), ('suited ace plus', 'A9s+', 20),\n  ('offsuit king plus', 'KTo+', 36), ('unsuffixed class', 'AK', 16),\n  ('dash kicker range', 'A9s-A6s', 16), ('dash pair range', 'TT-77', 24),\n  ('reversed kicker dash', 'K6o-K9o', 48)],\n [('offsuit king plus', 'KTo+', 36), ('unsuffixed class', 'AK', 16),\n  ('dash kicker range', 'A9s-A6s', 16), ('dash pair range', 'TT-77', 24),\n  ('reversed dash pairs', '77-TT', 24), ('spaced tokens', 'QQ+, AKs', 22),\n  ('overlap dedupe', 'AKs,AK', 16), ('reversed kicker dash', 'K6o-K9o', 48)],\n [('dash kicker range', 'A9s-A6s', 16), ('reversed dash pairs', '77-TT', 24),\n  ('spaced tokens', 'QQ+, AKs', 22), ('overlap dedupe', 'AKs,AK', 16), ('single pair', '22', 6),\n  ('mixed', 'JJ+,AQs+,KQo', 44), ('aces only', 'AA', 6), ('reversed kicker dash', 'K6o-K9o', 48)],\n [('pairs plus', '77+', 48), ('dash kicker range', 'A9s-A6s', 16), ('single pair', '22', 6),\n  ('mixed', 'JJ+,AQs+,KQo', 44), ('aces only', 'AA', 6), ('suited connector plus', 'T9s+', 4),\n  ('trailing comma', 'KK+,', 12), ('reversed kicker dash', 'K6o-K9o', 48)],\n [('pairs plus', '77+', 48), ('queens plus', 'QQ+', 18), ('suited ace plus', 'A9s+', 20),\n  ('offsuit king plus', 'KTo+', 36), ('dash kicker range', 'A9s-A6s', 16),\n  ('suited connector plus', 'T9s+', 4), ('trailing comma', 'KK+,', 12),\n  ('reversed kicker dash', 'K6o-K9o', 48)]]\nfor label, args, expected in fixtures[N-1]:\n    try:\n        actual = solve(args)\n    except Exception as exc:\n        actual = 'error:' + type(exc).__name__\n    check(label, actual, expected)\nprint(json.dumps({\"observations\": observations, \"passed\": all(x[\"passed\"] for x in observations)}, ensure_ascii=False))\nraise SystemExit(0 if all(x[\"passed\"] for x in observations) else 1)\n"},"fixed":{"sha256":"7f2bb6baf0053bb70e7320baaffa31ae7f375d11d9329bc7d7e71fbf6e5bc877","source":"\"\"\"Failure Map reference implementation. Python standard library only.\"\"\"\nimport json\n\nN = 1\nobservations = []\ndef solve(x):\n    R='23456789TJQKA'\n    classes=set()\n    def add(h, suf):\n        if h[0]==h[1]: classes.add(h)\n        elif suf: classes.add(h+suf)\n        else:\n            classes.add(h+'s'); classes.add(h+'o')\n    for tok in x.split(','):\n        tok=tok.strip()\n        if not tok: continue\n        plus=tok.endswith('+')\n        t=tok.rstrip('+')\n        if '-' in t:\n            a,b=t.split('-')\n            if a[0]==a[1]:\n                lo,hi=sorted([R.index(a[0]),R.index(b[0])])\n                for i in range(lo,hi+1): add(R[i]*2,'')\n            else:\n                lo,hi=sorted([R.index(a[1]),R.index(b[1])])\n                for i in range(lo,hi+1): add(a[0]+R[i],a[2:])\n            continue\n        if t[0]==t[1]:\n            start=R.index(t[0])\n            stop=len(R)-1 if plus else start\n            for i in range(start,stop+1): add(R[i]*2,'')\n        else:\n            top=R.index(t[0]); k=R.index(t[1])\n            stop=top-1 if plus else k\n            for i in range(k,stop+1): add(t[0]+R[i],t[2:])\n    total=0\n    for c in classes:\n        if c[0]==c[1]: total+=6\n        elif c.endswith('s'): total+=4\n        else: total+=12\n    return total\ndef check(label, actual, expected):\n    observations.append({\"check\": label, \"actual\": actual, \"expected\": expected, \"passed\": actual == expected})\nfixtures = [[('pairs plus', '77+', 48), ('queens plus', 'QQ+', 18), ('suited ace plus', 'A9s+', 20),\n  ('offsuit king plus', 'KTo+', 36), ('unsuffixed class', 'AK', 16),\n  ('dash kicker range', 'A9s-A6s', 16), ('dash pair range', 'TT-77', 24),\n  ('reversed kicker dash', 'K6o-K9o', 48)],\n [('offsuit king plus', 'KTo+', 36), ('unsuffixed class', 'AK', 16),\n  ('dash kicker range', 'A9s-A6s', 16), ('dash pair range', 'TT-77', 24),\n  ('reversed dash pairs', '77-TT', 24), ('spaced tokens', 'QQ+, AKs', 22),\n  ('overlap dedupe', 'AKs,AK', 16), ('reversed kicker dash', 'K6o-K9o', 48)],\n [('dash kicker range', 'A9s-A6s', 16), ('reversed dash pairs', '77-TT', 24),\n  ('spaced tokens', 'QQ+, AKs', 22), ('overlap dedupe', 'AKs,AK', 16), ('single pair', '22', 6),\n  ('mixed', 'JJ+,AQs+,KQo', 44), ('aces only', 'AA', 6), ('reversed kicker dash', 'K6o-K9o', 48)],\n [('pairs plus', '77+', 48), ('dash kicker range', 'A9s-A6s', 16), ('single pair', '22', 6),\n  ('mixed', 'JJ+,AQs+,KQo', 44), ('aces only', 'AA', 6), ('suited connector plus', 'T9s+', 4),\n  ('trailing comma', 'KK+,', 12), ('reversed kicker dash', 'K6o-K9o', 48)],\n [('pairs plus', '77+', 48), ('queens plus', 'QQ+', 18), ('suited ace plus', 'A9s+', 20),\n  ('offsuit king plus', 'KTo+', 36), ('dash kicker range', 'A9s-A6s', 16),\n  ('suited connector plus', 'T9s+', 4), ('trailing comma', 'KK+,', 12),\n  ('reversed kicker dash', 'K6o-K9o', 48)]]\nfor label, args, expected in fixtures[N-1]:\n    try:\n        actual = solve(args)\n    except Exception as exc:\n        actual = 'error:' + type(exc).__name__\n    check(label, actual, expected)\nprint(json.dumps({\"observations\": observations, \"passed\": all(x[\"passed\"] for x in observations)}, ensure_ascii=False))\nraise SystemExit(0 if all(x[\"passed\"] for x in observations) else 1)\n"}},"limitations":"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.","method":"Deterministic executable model with adversarial boundary fixtures.","provenance":{"created_by":"Failure Map","dependencies":"Python standard library","family":"w2-poker_hand_evaluation-range-combo-count-dash-range-inclusivity","generated_at":"2026-09-29T14:50:09.427022+00:00","license":"CC0-1.0","python":"3.12.14","seed":1,"split":"open-access"},"relevance":"Range combo counts drive equity, frequency and blocker arithmetic in solvers and trackers.","repair":"Both ends of a dash range are inclusive.","root_cause":"The dash range uses a half-open interval, so the higher named kicker is excluded.","sha256":"2e2c9c31ffc8b3879bad0cb21f2d9e9377a4fc9cb8c3b45e170415f0af9c16dd","title":"Kicker dash range drops its upper end · case 01","variant":1,"variant_policy":"Five numbered records share a model and may reuse boundary fixtures.","verification":{"attempt":{"elapsed_ms":42.851,"exit_code":1,"observations":[{"actual":48,"check":"pairs plus","expected":48,"passed":true},{"actual":18,"check":"queens plus","expected":18,"passed":true},{"actual":20,"check":"suited ace plus","expected":20,"passed":true},{"actual":36,"check":"offsuit king plus","expected":36,"passed":true},{"actual":16,"check":"unsuffixed class","expected":16,"passed":true},{"actual":12,"check":"dash kicker range","expected":16,"passed":false},{"actual":24,"check":"dash pair range","expected":24,"passed":true},{"actual":36,"check":"reversed kicker dash","expected":48,"passed":false}],"passed":false,"stderr":"","stdout":"{\"observations\": [{\"check\": \"pairs plus\", \"actual\": 48, \"expected\": 48, \"passed\": true}, {\"check\": \"queens plus\", \"actual\": 18, \"expected\": 18, \"passed\": true}, {\"check\": \"suited ace plus\", \"actual\": 20, \"expected\": 20, \"passed\": true}, {\"check\": \"offsuit king plus\", \"actual\": 36, \"expected\": 36, \"passed\": true}, {\"check\": \"unsuffixed class\", \"actual\": 16, \"expected\": 16, \"passed\": true}, {\"check\": \"dash kicker range\", \"actual\": 12, \"expected\": 16, \"passed\": false}, {\"check\": \"dash pair range\", \"actual\": 24, \"expected\": 24, \"passed\": true}, {\"check\": \"reversed kicker dash\", \"actual\": 36, \"expected\": 48, \"passed\": false}], \"passed\": false}\n"},"broken":{"elapsed_ms":40.673,"exit_code":1,"observations":[{"actual":48,"check":"pairs plus","expected":48,"passed":true},{"actual":18,"check":"queens plus","expected":18,"passed":true},{"actual":20,"check":"suited ace plus","expected":20,"passed":true},{"actual":36,"check":"offsuit king plus","expected":36,"passed":true},{"actual":16,"check":"unsuffixed class","expected":16,"passed":true},{"actual":12,"check":"dash kicker range","expected":16,"passed":false},{"actual":24,"check":"dash pair range","expected":24,"passed":true},{"actual":36,"check":"reversed kicker dash","expected":48,"passed":false}],"passed":false,"stderr":"","stdout":"{\"observations\": [{\"check\": \"pairs plus\", \"actual\": 48, \"expected\": 48, \"passed\": true}, {\"check\": \"queens plus\", \"actual\": 18, \"expected\": 18, \"passed\": true}, {\"check\": \"suited ace plus\", \"actual\": 20, \"expected\": 20, \"passed\": true}, {\"check\": \"offsuit king plus\", \"actual\": 36, \"expected\": 36, \"passed\": true}, {\"check\": \"unsuffixed class\", \"actual\": 16, \"expected\": 16, \"passed\": true}, {\"check\": \"dash kicker range\", \"actual\": 12, \"expected\": 16, \"passed\": false}, {\"check\": \"dash pair range\", \"actual\": 24, \"expected\": 24, \"passed\": true}, {\"check\": \"reversed kicker dash\", \"actual\": 36, \"expected\": 48, \"passed\": false}], \"passed\": false}\n"},"fixed":{"elapsed_ms":40.646,"exit_code":0,"observations":[{"actual":48,"check":"pairs plus","expected":48,"passed":true},{"actual":18,"check":"queens plus","expected":18,"passed":true},{"actual":20,"check":"suited ace plus","expected":20,"passed":true},{"actual":36,"check":"offsuit king plus","expected":36,"passed":true},{"actual":16,"check":"unsuffixed class","expected":16,"passed":true},{"actual":16,"check":"dash kicker range","expected":16,"passed":true},{"actual":24,"check":"dash pair range","expected":24,"passed":true},{"actual":48,"check":"reversed kicker dash","expected":48,"passed":true}],"passed":true,"stderr":"","stdout":"{\"observations\": [{\"check\": \"pairs plus\", \"actual\": 48, \"expected\": 48, \"passed\": true}, {\"check\": \"queens plus\", \"actual\": 18, \"expected\": 18, \"passed\": true}, {\"check\": \"suited ace plus\", \"actual\": 20, \"expected\": 20, \"passed\": true}, {\"check\": \"offsuit king plus\", \"actual\": 36, \"expected\": 36, \"passed\": true}, {\"check\": \"unsuffixed class\", \"actual\": 16, \"expected\": 16, \"passed\": true}, {\"check\": \"dash kicker range\", \"actual\": 16, \"expected\": 16, \"passed\": true}, {\"check\": \"dash pair range\", \"actual\": 24, \"expected\": 24, \"passed\": true}, {\"check\": \"reversed kicker dash\", \"actual\": 48, \"expected\": 48, \"passed\": true}], \"passed\": true}\n"}},"verified":true,"visibility":"public"}