FA-72501 / Check-digit algorithms / Open access
VIN transliterates S as 1 · case 01
VINs containing S get the wrong check digit.
ROOT CAUSE
The table maps S to 1 by continuing the J..R numbering, but the standard restarts S at 2.
VERIFIED REPAIR
Map S to 2 (S-Z transliterate to 2-9).
Unsuccessful approach: Mapping S to 0 treats it like a numeric O-substitute and is still wrong.
Case contract
North American 17-character VIN check digit. Input must be 17 uppercase ASCII alphanumerics without I, O or Q (else "malformed"). Letters transliterate (A-H 1-8, J-N 1-5, P 7, R 9, S-Z 2-9); weights are 8,7,6,5,4,3,2,10,0,9,8,7,6,5,4,3,2 with weight 0 on the check position (9th). Remainder mod 11 is the check digit, 10 written X. Return [check character, whether position 9 matches].
Why this case matters
Vehicle registration and recall systems reject VINs with a bad check digit.
1 / The failure
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(vin):
TR = {'A': 1, 'B': 2, 'C': 3, 'D': 4, 'E': 5, 'F': 6, 'G': 7, 'H': 8, 'J': 1, 'K': 2, 'L': 3, 'M': 4, 'N': 5, 'P': 7, 'R': 9, 'S': 1, 'T': 3, 'U': 4, 'V': 5, 'W': 6, 'X': 7, 'Y': 8, 'Z': 9}
W = [8, 7, 6, 5, 4, 3, 2, 10, 0, 9, 8, 7, 6, 5, 4, 3, 2]
if len(vin) != 17 or not vin.isascii() or not vin.isalnum() or vin != vin.upper():
return 'malformed'
if any(ch in 'IOQ' for ch in vin):
return 'malformed'
total = 0
for ch, w in zip(vin, W):
total += (int(ch) if ch.isdigit() else TR[ch]) * w
r = total % 11
check = 'X' if r == 10 else str(r)
return [check, vin[8] == check]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression ["5E80302J20HS0C2TB"]', ['5E80302J20HS0C2TB'], ['X', False]], ['regression ["T32AS501XMK3869UE"]', ['T32AS501XMK3869UE'], ['7', False]], ['control ["7P852FPZ9AMB30TWM"]', ['7P852FPZ9AMB30TWM'], ['1', False]], ['control ["NRCAB2B221G6DGFEU"]', ['NRCAB2B221G6DGFEU'], ['3', False]], ['control ["802LPLKT5RR2033BP"]', ['802LPLKT5RR2033BP'], ['2', False]], ['control ["G9Y36GVM3T01TBX5P"]', ['G9Y36GVM3T01TBX5P'], ['0', False]], ['control ["J5KCLF4060VP1YCZT"]', ['J5KCLF4060VP1YCZT'], ['2', False]], ['control ["7U176LUC2HMRHV49Y"]', ['7U176LUC2HMRHV49Y'], ['0', False]]], [['regression ["4E2898314S7811191"]', ['4E2898314S7811191'], ['6', False]], ['regression ["952403649S86181S3"]', ['952403649S86181S3'], ['1', False]], ['control ["7U176LUC2HMRHV49Y"]', ['7U176LUC2HMRHV49Y'], ['0', False]], ['control ["9D9WJN8Z6UAEAXNMY"]', ['9D9WJN8Z6UAEAXNMY'], ['4', False]], ['control ["G746XY1N49VVXVM2N"]', ['G746XY1N49VVXVM2N'], ['1', False]], ['control ["ZP4DXW7F59ZF0J6LD"]', ['ZP4DXW7F59ZF0J6LD'], ['9', False]], ['control ["XASS3C3Z3KGD2JETV"]', ['XASS3C3Z3KGD2JETV'], ['8', False]], ['control ["466JDFJ71TZ0MJCXA"]', ['466JDFJ71TZ0MJCXA'], ['X', False]]], [['regression ["6C2F00FD7S2507305"]', ['6C2F00FD7S2507305'], ['3', False]], ['regression ["5YJSA1E14HF000001"]', ['5YJSA1E14HF000001'], ['8', False]], ['control ["466JDFJ71TZ0MJCXA"]', ['466JDFJ71TZ0MJCXA'], ['X', False]], ['control ["1M8GDM9AXKP042788"]', ['1M8GDM9AXKP042788'], ['X', True]], ['control ["11111111111111111"]', ['11111111111111111'], ['1', True]], ['control ["1HGCM82633A004352"]', ['1HGCM82633A004352'], ['3', True]], ['control ["JH4KA7561PC008269"]', ['JH4KA7561PC008269'], ['1', True]], ['control ["1M8GDM9AXKP04278"]', ['1M8GDM9AXKP04278'], 'malformed']], [['regression ["5E80302J20HS0C2TB"]', ['5E80302J20HS0C2TB'], ['X', False]], ['regression ["T32AS501XMK3869UE"]', ['T32AS501XMK3869UE'], ['7', False]], ['control ["1M8GDM9AXKP04278"]', ['1M8GDM9AXKP04278'], 'malformed'], ['control ["1M8GDM9AXKP04278O"]', ['1M8GDM9AXKP04278O'], 'malformed'], ['control ["1m8gdm9axkp042788"]', ['1m8gdm9axkp042788'], 'malformed'], ['control ["WVWZZZ1JZ3W386752"]', ['WVWZZZ1JZ3W386752'], ['9', False]], ['control ["7P852FPZ9AMB30TWM"]', ['7P852FPZ9AMB30TWM'], ['1', False]], ['control ["NRCAB2B221G6DGFEU"]', ['NRCAB2B221G6DGFEU'], ['3', False]]], [['regression ["4E2898314S7811191"]', ['4E2898314S7811191'], ['6', False]], ['regression ["952403649S86181S3"]', ['952403649S86181S3'], ['1', False]], ['control ["NRCAB2B221G6DGFEU"]', ['NRCAB2B221G6DGFEU'], ['3', False]], ['control ["802LPLKT5RR2033BP"]', ['802LPLKT5RR2033BP'], ['2', False]], ['control ["G9Y36GVM3T01TBX5P"]', ['G9Y36GVM3T01TBX5P'], ['0', False]], ['control ["J5KCLF4060VP1YCZT"]', ['J5KCLF4060VP1YCZT'], ['2', False]], ['control ["7U176LUC2HMRHV49Y"]', ['7U176LUC2HMRHV49Y'], ['0', False]], ['control ["9D9WJN8Z6UAEAXNMY"]', ['9D9WJN8Z6UAEAXNMY'], ['4', False]]]]
for label, args, expected in fixtures[N - 1]:
check(label, 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 |
|---|---|---|---|
| regression ["5E80302J20HS0C2TB"] | ['3', False] | ['X', False] | Failed |
| regression ["T32AS501XMK3869UE"] | ['3', False] | ['7', False] | Failed |
| control ["7P852FPZ9AMB30TWM"] | ['1', False] | ['1', False] | Passed |
| control ["NRCAB2B221G6DGFEU"] | ['3', False] | ['3', False] | Passed |
| control ["802LPLKT5RR2033BP"] | ['2', False] | ['2', False] | Passed |
| control ["G9Y36GVM3T01TBX5P"] | ['0', False] | ['0', False] | Passed |
| control ["J5KCLF4060VP1YCZT"] | ['2', False] | ['2', False] | Passed |
| control ["7U176LUC2HMRHV49Y"] | ['0', False] | ['0', False] | Passed |
SHA-256 / e202a827717d4bd19c6b4aec4060b0ca9f1a81324310a9cd21153bd33a102d5e
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(vin):
TR = {'A': 1, 'B': 2, 'C': 3, 'D': 4, 'E': 5, 'F': 6, 'G': 7, 'H': 8, 'J': 1, 'K': 2, 'L': 3, 'M': 4, 'N': 5, 'P': 7, 'R': 9, 'S': 0, 'T': 3, 'U': 4, 'V': 5, 'W': 6, 'X': 7, 'Y': 8, 'Z': 9}
W = [8, 7, 6, 5, 4, 3, 2, 10, 0, 9, 8, 7, 6, 5, 4, 3, 2]
if len(vin) != 17 or not vin.isascii() or not vin.isalnum() or vin != vin.upper():
return 'malformed'
if any(ch in 'IOQ' for ch in vin):
return 'malformed'
total = 0
for ch, w in zip(vin, W):
total += (int(ch) if ch.isdigit() else TR[ch]) * w
r = total % 11
check = 'X' if r == 10 else str(r)
return [check, vin[8] == check]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression ["5E80302J20HS0C2TB"]', ['5E80302J20HS0C2TB'], ['X', False]], ['regression ["T32AS501XMK3869UE"]', ['T32AS501XMK3869UE'], ['7', False]], ['control ["7P852FPZ9AMB30TWM"]', ['7P852FPZ9AMB30TWM'], ['1', False]], ['control ["NRCAB2B221G6DGFEU"]', ['NRCAB2B221G6DGFEU'], ['3', False]], ['control ["802LPLKT5RR2033BP"]', ['802LPLKT5RR2033BP'], ['2', False]], ['control ["G9Y36GVM3T01TBX5P"]', ['G9Y36GVM3T01TBX5P'], ['0', False]], ['control ["J5KCLF4060VP1YCZT"]', ['J5KCLF4060VP1YCZT'], ['2', False]], ['control ["7U176LUC2HMRHV49Y"]', ['7U176LUC2HMRHV49Y'], ['0', False]]], [['regression ["4E2898314S7811191"]', ['4E2898314S7811191'], ['6', False]], ['regression ["952403649S86181S3"]', ['952403649S86181S3'], ['1', False]], ['control ["7U176LUC2HMRHV49Y"]', ['7U176LUC2HMRHV49Y'], ['0', False]], ['control ["9D9WJN8Z6UAEAXNMY"]', ['9D9WJN8Z6UAEAXNMY'], ['4', False]], ['control ["G746XY1N49VVXVM2N"]', ['G746XY1N49VVXVM2N'], ['1', False]], ['control ["ZP4DXW7F59ZF0J6LD"]', ['ZP4DXW7F59ZF0J6LD'], ['9', False]], ['control ["XASS3C3Z3KGD2JETV"]', ['XASS3C3Z3KGD2JETV'], ['8', False]], ['control ["466JDFJ71TZ0MJCXA"]', ['466JDFJ71TZ0MJCXA'], ['X', False]]], [['regression ["6C2F00FD7S2507305"]', ['6C2F00FD7S2507305'], ['3', False]], ['regression ["5YJSA1E14HF000001"]', ['5YJSA1E14HF000001'], ['8', False]], ['control ["466JDFJ71TZ0MJCXA"]', ['466JDFJ71TZ0MJCXA'], ['X', False]], ['control ["1M8GDM9AXKP042788"]', ['1M8GDM9AXKP042788'], ['X', True]], ['control ["11111111111111111"]', ['11111111111111111'], ['1', True]], ['control ["1HGCM82633A004352"]', ['1HGCM82633A004352'], ['3', True]], ['control ["JH4KA7561PC008269"]', ['JH4KA7561PC008269'], ['1', True]], ['control ["1M8GDM9AXKP04278"]', ['1M8GDM9AXKP04278'], 'malformed']], [['regression ["5E80302J20HS0C2TB"]', ['5E80302J20HS0C2TB'], ['X', False]], ['regression ["T32AS501XMK3869UE"]', ['T32AS501XMK3869UE'], ['7', False]], ['control ["1M8GDM9AXKP04278"]', ['1M8GDM9AXKP04278'], 'malformed'], ['control ["1M8GDM9AXKP04278O"]', ['1M8GDM9AXKP04278O'], 'malformed'], ['control ["1m8gdm9axkp042788"]', ['1m8gdm9axkp042788'], 'malformed'], ['control ["WVWZZZ1JZ3W386752"]', ['WVWZZZ1JZ3W386752'], ['9', False]], ['control ["7P852FPZ9AMB30TWM"]', ['7P852FPZ9AMB30TWM'], ['1', False]], ['control ["NRCAB2B221G6DGFEU"]', ['NRCAB2B221G6DGFEU'], ['3', False]]], [['regression ["4E2898314S7811191"]', ['4E2898314S7811191'], ['6', False]], ['regression ["952403649S86181S3"]', ['952403649S86181S3'], ['1', False]], ['control ["NRCAB2B221G6DGFEU"]', ['NRCAB2B221G6DGFEU'], ['3', False]], ['control ["802LPLKT5RR2033BP"]', ['802LPLKT5RR2033BP'], ['2', False]], ['control ["G9Y36GVM3T01TBX5P"]', ['G9Y36GVM3T01TBX5P'], ['0', False]], ['control ["J5KCLF4060VP1YCZT"]', ['J5KCLF4060VP1YCZT'], ['2', False]], ['control ["7U176LUC2HMRHV49Y"]', ['7U176LUC2HMRHV49Y'], ['0', False]], ['control ["9D9WJN8Z6UAEAXNMY"]', ['9D9WJN8Z6UAEAXNMY'], ['4', False]]]]
for label, args, expected in fixtures[N - 1]:
check(label, 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 |
|---|---|---|---|
| regression ["5E80302J20HS0C2TB"] | ['7', False] | ['X', False] | Failed |
| regression ["T32AS501XMK3869UE"] | ['X', True] | ['7', False] | Failed |
| control ["7P852FPZ9AMB30TWM"] | ['1', False] | ['1', False] | Passed |
| control ["NRCAB2B221G6DGFEU"] | ['3', False] | ['3', False] | Passed |
| control ["802LPLKT5RR2033BP"] | ['2', False] | ['2', False] | Passed |
| control ["G9Y36GVM3T01TBX5P"] | ['0', False] | ['0', False] | Passed |
| control ["J5KCLF4060VP1YCZT"] | ['2', False] | ['2', False] | Passed |
| control ["7U176LUC2HMRHV49Y"] | ['0', False] | ['0', False] | Passed |
SHA-256 / a3ea9f32ac4be811c61b7a976b3311f79c892540c20854d49491750eeb793434
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(vin):
TR = {'A': 1, 'B': 2, 'C': 3, 'D': 4, 'E': 5, 'F': 6, 'G': 7, 'H': 8, 'J': 1, 'K': 2, 'L': 3, 'M': 4, 'N': 5, 'P': 7, 'R': 9, 'S': 2, 'T': 3, 'U': 4, 'V': 5, 'W': 6, 'X': 7, 'Y': 8, 'Z': 9}
W = [8, 7, 6, 5, 4, 3, 2, 10, 0, 9, 8, 7, 6, 5, 4, 3, 2]
if len(vin) != 17 or not vin.isascii() or not vin.isalnum() or vin != vin.upper():
return 'malformed'
if any(ch in 'IOQ' for ch in vin):
return 'malformed'
total = 0
for ch, w in zip(vin, W):
total += (int(ch) if ch.isdigit() else TR[ch]) * w
r = total % 11
check = 'X' if r == 10 else str(r)
return [check, vin[8] == check]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression ["5E80302J20HS0C2TB"]', ['5E80302J20HS0C2TB'], ['X', False]], ['regression ["T32AS501XMK3869UE"]', ['T32AS501XMK3869UE'], ['7', False]], ['control ["7P852FPZ9AMB30TWM"]', ['7P852FPZ9AMB30TWM'], ['1', False]], ['control ["NRCAB2B221G6DGFEU"]', ['NRCAB2B221G6DGFEU'], ['3', False]], ['control ["802LPLKT5RR2033BP"]', ['802LPLKT5RR2033BP'], ['2', False]], ['control ["G9Y36GVM3T01TBX5P"]', ['G9Y36GVM3T01TBX5P'], ['0', False]], ['control ["J5KCLF4060VP1YCZT"]', ['J5KCLF4060VP1YCZT'], ['2', False]], ['control ["7U176LUC2HMRHV49Y"]', ['7U176LUC2HMRHV49Y'], ['0', False]]], [['regression ["4E2898314S7811191"]', ['4E2898314S7811191'], ['6', False]], ['regression ["952403649S86181S3"]', ['952403649S86181S3'], ['1', False]], ['control ["7U176LUC2HMRHV49Y"]', ['7U176LUC2HMRHV49Y'], ['0', False]], ['control ["9D9WJN8Z6UAEAXNMY"]', ['9D9WJN8Z6UAEAXNMY'], ['4', False]], ['control ["G746XY1N49VVXVM2N"]', ['G746XY1N49VVXVM2N'], ['1', False]], ['control ["ZP4DXW7F59ZF0J6LD"]', ['ZP4DXW7F59ZF0J6LD'], ['9', False]], ['control ["XASS3C3Z3KGD2JETV"]', ['XASS3C3Z3KGD2JETV'], ['8', False]], ['control ["466JDFJ71TZ0MJCXA"]', ['466JDFJ71TZ0MJCXA'], ['X', False]]], [['regression ["6C2F00FD7S2507305"]', ['6C2F00FD7S2507305'], ['3', False]], ['regression ["5YJSA1E14HF000001"]', ['5YJSA1E14HF000001'], ['8', False]], ['control ["466JDFJ71TZ0MJCXA"]', ['466JDFJ71TZ0MJCXA'], ['X', False]], ['control ["1M8GDM9AXKP042788"]', ['1M8GDM9AXKP042788'], ['X', True]], ['control ["11111111111111111"]', ['11111111111111111'], ['1', True]], ['control ["1HGCM82633A004352"]', ['1HGCM82633A004352'], ['3', True]], ['control ["JH4KA7561PC008269"]', ['JH4KA7561PC008269'], ['1', True]], ['control ["1M8GDM9AXKP04278"]', ['1M8GDM9AXKP04278'], 'malformed']], [['regression ["5E80302J20HS0C2TB"]', ['5E80302J20HS0C2TB'], ['X', False]], ['regression ["T32AS501XMK3869UE"]', ['T32AS501XMK3869UE'], ['7', False]], ['control ["1M8GDM9AXKP04278"]', ['1M8GDM9AXKP04278'], 'malformed'], ['control ["1M8GDM9AXKP04278O"]', ['1M8GDM9AXKP04278O'], 'malformed'], ['control ["1m8gdm9axkp042788"]', ['1m8gdm9axkp042788'], 'malformed'], ['control ["WVWZZZ1JZ3W386752"]', ['WVWZZZ1JZ3W386752'], ['9', False]], ['control ["7P852FPZ9AMB30TWM"]', ['7P852FPZ9AMB30TWM'], ['1', False]], ['control ["NRCAB2B221G6DGFEU"]', ['NRCAB2B221G6DGFEU'], ['3', False]]], [['regression ["4E2898314S7811191"]', ['4E2898314S7811191'], ['6', False]], ['regression ["952403649S86181S3"]', ['952403649S86181S3'], ['1', False]], ['control ["NRCAB2B221G6DGFEU"]', ['NRCAB2B221G6DGFEU'], ['3', False]], ['control ["802LPLKT5RR2033BP"]', ['802LPLKT5RR2033BP'], ['2', False]], ['control ["G9Y36GVM3T01TBX5P"]', ['G9Y36GVM3T01TBX5P'], ['0', False]], ['control ["J5KCLF4060VP1YCZT"]', ['J5KCLF4060VP1YCZT'], ['2', False]], ['control ["7U176LUC2HMRHV49Y"]', ['7U176LUC2HMRHV49Y'], ['0', False]], ['control ["9D9WJN8Z6UAEAXNMY"]', ['9D9WJN8Z6UAEAXNMY'], ['4', False]]]]
for label, args, expected in fixtures[N - 1]:
check(label, 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 |
|---|---|---|---|
| regression ["5E80302J20HS0C2TB"] | ['X', False] | ['X', False] | Passed |
| regression ["T32AS501XMK3869UE"] | ['7', False] | ['7', False] | Passed |
| control ["7P852FPZ9AMB30TWM"] | ['1', False] | ['1', False] | Passed |
| control ["NRCAB2B221G6DGFEU"] | ['3', False] | ['3', False] | Passed |
| control ["802LPLKT5RR2033BP"] | ['2', False] | ['2', False] | Passed |
| control ["G9Y36GVM3T01TBX5P"] | ['0', False] | ['0', False] | Passed |
| control ["J5KCLF4060VP1YCZT"] | ['2', False] | ['2', False] | Passed |
| control ["7U176LUC2HMRHV49Y"] | ['0', False] | ['0', False] | Passed |
SHA-256 / 4e0a65a20e34e06bba7ed2023912f37d83b10f7f1ec82c3658467265019c9dc3
Verification & scope
A deterministic, bounded teaching model of the named scheme under the stated contract; not a certified validator. 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:48:39.039019+00:00.
Case digest / 2975890da79e30c758562125e7ddd4a72797e77f0a6986e421e7e9b1f2261bba