FA-72516 / Check-digit algorithms / Open access
VIN compares the model-year character · case 01
Correct VINs are rejected unless positions 9 and 10 happen to match.
ROOT CAUSE
The comparison uses vin[9] (the 1-based position number) instead of 0-based index 8.
VERIFIED REPAIR
Compare the computed check against vin[8].
Unsuccessful approach: Using vin[7] moves the comparison to the vehicle-descriptor character.
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': 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[9] == check]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression ["ZP4DXW7F59ZF0J6LD"]', ['ZP4DXW7F59ZF0J6LD'], ['9', False]], ['regression ["1M8GDM9AXKP042788"]', ['1M8GDM9AXKP042788'], ['X', True]], ['partial-repair ["1HGCM82633A004352"]', ['1HGCM82633A004352'], ['3', True]], ['control ["7P852FPZ9AMB30TWM"]', ['7P852FPZ9AMB30TWM'], ['1', False]], ['control ["5E80302J20HS0C2TB"]', ['5E80302J20HS0C2TB'], ['X', False]], ['control ["NRCAB2B221G6DGFEU"]', ['NRCAB2B221G6DGFEU'], ['3', False]], ['control ["802LPLKT5RR2033BP"]', ['802LPLKT5RR2033BP'], ['2', False]], ['control ["G9Y36GVM3T01TBX5P"]', ['G9Y36GVM3T01TBX5P'], ['0', False]]], [['regression ["ZP4DXW7F59ZF0J6LD"]', ['ZP4DXW7F59ZF0J6LD'], ['9', False]], ['regression ["1M8GDM9AXKP042788"]', ['1M8GDM9AXKP042788'], ['X', True]], ['partial-repair ["1HGCM82633A004352"]', ['1HGCM82633A004352'], ['3', True]], ['control ["J5KCLF4060VP1YCZT"]', ['J5KCLF4060VP1YCZT'], ['2', False]], ['control ["7U176LUC2HMRHV49Y"]', ['7U176LUC2HMRHV49Y'], ['0', False]], ['control ["T32AS501XMK3869UE"]', ['T32AS501XMK3869UE'], ['7', False]], ['control ["9D9WJN8Z6UAEAXNMY"]', ['9D9WJN8Z6UAEAXNMY'], ['4', False]], ['control ["G746XY1N49VVXVM2N"]', ['G746XY1N49VVXVM2N'], ['1', False]]], [['regression ["ZP4DXW7F59ZF0J6LD"]', ['ZP4DXW7F59ZF0J6LD'], ['9', False]], ['regression ["1M8GDM9AXKP042788"]', ['1M8GDM9AXKP042788'], ['X', True]], ['partial-repair ["1HGCM82633A004352"]', ['1HGCM82633A004352'], ['3', True]], ['control ["A2C3SUET4AT9FGY0N"]', ['A2C3SUET4AT9FGY0N'], ['5', False]], ['control ["XASS3C3Z3KGD2JETV"]', ['XASS3C3Z3KGD2JETV'], ['8', False]], ['control ["466JDFJ71TZ0MJCXA"]', ['466JDFJ71TZ0MJCXA'], ['X', False]], ['control ["4E2898314S7811191"]', ['4E2898314S7811191'], ['6', False]], ['control ["952403649S86181S3"]', ['952403649S86181S3'], ['1', False]]], [['regression ["ZP4DXW7F59ZF0J6LD"]', ['ZP4DXW7F59ZF0J6LD'], ['9', False]], ['regression ["1M8GDM9AXKP042788"]', ['1M8GDM9AXKP042788'], ['X', True]], ['partial-repair ["1HGCM82633A004352"]', ['1HGCM82633A004352'], ['3', True]], ['control ["F32A05CF4S3S80512"]', ['F32A05CF4S3S80512'], ['1', False]], ['control ["6C2F00FD7S2507305"]', ['6C2F00FD7S2507305'], ['3', False]], ['control ["11111111111111111"]', ['11111111111111111'], ['1', True]], ['control ["1M8GDM9AXKP04278"]', ['1M8GDM9AXKP04278'], 'malformed'], ['control ["1M8GDM9AXKP04278O"]', ['1M8GDM9AXKP04278O'], 'malformed']], [['regression ["ZP4DXW7F59ZF0J6LD"]', ['ZP4DXW7F59ZF0J6LD'], ['9', False]], ['regression ["1M8GDM9AXKP042788"]', ['1M8GDM9AXKP042788'], ['X', True]], ['partial-repair ["1HGCM82633A004352"]', ['1HGCM82633A004352'], ['3', True]], ['control ["1m8gdm9axkp042788"]', ['1m8gdm9axkp042788'], 'malformed'], ['control ["5YJSA1E14HF000001"]', ['5YJSA1E14HF000001'], ['8', False]], ['control ["WVWZZZ1JZ3W386752"]', ['WVWZZZ1JZ3W386752'], ['9', False]], ['control ["SALVA2AE4EH877482"]', ['SALVA2AE4EH877482'], ['7', False]], ['control ["7P852FPZ9AMB30TWM"]', ['7P852FPZ9AMB30TWM'], ['1', 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 ["ZP4DXW7F59ZF0J6LD"] | ['9', True] | ['9', False] | Failed |
| regression ["1M8GDM9AXKP042788"] | ['X', False] | ['X', True] | Failed |
| partial-repair ["1HGCM82633A004352"] | ['3', True] | ['3', True] | Passed |
| control ["7P852FPZ9AMB30TWM"] | ['1', False] | ['1', False] | Passed |
| control ["5E80302J20HS0C2TB"] | ['X', False] | ['X', False] | Passed |
| control ["NRCAB2B221G6DGFEU"] | ['3', False] | ['3', False] | Passed |
| control ["802LPLKT5RR2033BP"] | ['2', False] | ['2', False] | Passed |
| control ["G9Y36GVM3T01TBX5P"] | ['0', False] | ['0', False] | Passed |
SHA-256 / 156ce7e550942302c3f25418111ac792e38a1d72b22aa40133a3c64bbff92363
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': 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[7] == check]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression ["ZP4DXW7F59ZF0J6LD"]', ['ZP4DXW7F59ZF0J6LD'], ['9', False]], ['regression ["1M8GDM9AXKP042788"]', ['1M8GDM9AXKP042788'], ['X', True]], ['partial-repair ["1HGCM82633A004352"]', ['1HGCM82633A004352'], ['3', True]], ['control ["7P852FPZ9AMB30TWM"]', ['7P852FPZ9AMB30TWM'], ['1', False]], ['control ["5E80302J20HS0C2TB"]', ['5E80302J20HS0C2TB'], ['X', False]], ['control ["NRCAB2B221G6DGFEU"]', ['NRCAB2B221G6DGFEU'], ['3', False]], ['control ["802LPLKT5RR2033BP"]', ['802LPLKT5RR2033BP'], ['2', False]], ['control ["G9Y36GVM3T01TBX5P"]', ['G9Y36GVM3T01TBX5P'], ['0', False]]], [['regression ["ZP4DXW7F59ZF0J6LD"]', ['ZP4DXW7F59ZF0J6LD'], ['9', False]], ['regression ["1M8GDM9AXKP042788"]', ['1M8GDM9AXKP042788'], ['X', True]], ['partial-repair ["1HGCM82633A004352"]', ['1HGCM82633A004352'], ['3', True]], ['control ["J5KCLF4060VP1YCZT"]', ['J5KCLF4060VP1YCZT'], ['2', False]], ['control ["7U176LUC2HMRHV49Y"]', ['7U176LUC2HMRHV49Y'], ['0', False]], ['control ["T32AS501XMK3869UE"]', ['T32AS501XMK3869UE'], ['7', False]], ['control ["9D9WJN8Z6UAEAXNMY"]', ['9D9WJN8Z6UAEAXNMY'], ['4', False]], ['control ["G746XY1N49VVXVM2N"]', ['G746XY1N49VVXVM2N'], ['1', False]]], [['regression ["ZP4DXW7F59ZF0J6LD"]', ['ZP4DXW7F59ZF0J6LD'], ['9', False]], ['regression ["1M8GDM9AXKP042788"]', ['1M8GDM9AXKP042788'], ['X', True]], ['partial-repair ["1HGCM82633A004352"]', ['1HGCM82633A004352'], ['3', True]], ['control ["A2C3SUET4AT9FGY0N"]', ['A2C3SUET4AT9FGY0N'], ['5', False]], ['control ["XASS3C3Z3KGD2JETV"]', ['XASS3C3Z3KGD2JETV'], ['8', False]], ['control ["466JDFJ71TZ0MJCXA"]', ['466JDFJ71TZ0MJCXA'], ['X', False]], ['control ["4E2898314S7811191"]', ['4E2898314S7811191'], ['6', False]], ['control ["952403649S86181S3"]', ['952403649S86181S3'], ['1', False]]], [['regression ["ZP4DXW7F59ZF0J6LD"]', ['ZP4DXW7F59ZF0J6LD'], ['9', False]], ['regression ["1M8GDM9AXKP042788"]', ['1M8GDM9AXKP042788'], ['X', True]], ['partial-repair ["1HGCM82633A004352"]', ['1HGCM82633A004352'], ['3', True]], ['control ["F32A05CF4S3S80512"]', ['F32A05CF4S3S80512'], ['1', False]], ['control ["6C2F00FD7S2507305"]', ['6C2F00FD7S2507305'], ['3', False]], ['control ["11111111111111111"]', ['11111111111111111'], ['1', True]], ['control ["1M8GDM9AXKP04278"]', ['1M8GDM9AXKP04278'], 'malformed'], ['control ["1M8GDM9AXKP04278O"]', ['1M8GDM9AXKP04278O'], 'malformed']], [['regression ["ZP4DXW7F59ZF0J6LD"]', ['ZP4DXW7F59ZF0J6LD'], ['9', False]], ['regression ["1M8GDM9AXKP042788"]', ['1M8GDM9AXKP042788'], ['X', True]], ['partial-repair ["1HGCM82633A004352"]', ['1HGCM82633A004352'], ['3', True]], ['control ["1m8gdm9axkp042788"]', ['1m8gdm9axkp042788'], 'malformed'], ['control ["5YJSA1E14HF000001"]', ['5YJSA1E14HF000001'], ['8', False]], ['control ["WVWZZZ1JZ3W386752"]', ['WVWZZZ1JZ3W386752'], ['9', False]], ['control ["SALVA2AE4EH877482"]', ['SALVA2AE4EH877482'], ['7', False]], ['control ["7P852FPZ9AMB30TWM"]', ['7P852FPZ9AMB30TWM'], ['1', 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 ["ZP4DXW7F59ZF0J6LD"] | ['9', False] | ['9', False] | Passed |
| regression ["1M8GDM9AXKP042788"] | ['X', False] | ['X', True] | Failed |
| partial-repair ["1HGCM82633A004352"] | ['3', False] | ['3', True] | Failed |
| control ["7P852FPZ9AMB30TWM"] | ['1', False] | ['1', False] | Passed |
| control ["5E80302J20HS0C2TB"] | ['X', False] | ['X', False] | Passed |
| control ["NRCAB2B221G6DGFEU"] | ['3', False] | ['3', False] | Passed |
| control ["802LPLKT5RR2033BP"] | ['2', False] | ['2', False] | Passed |
| control ["G9Y36GVM3T01TBX5P"] | ['0', False] | ['0', False] | Passed |
SHA-256 / a438996aab00e540a161825818df6eebd70c8f96f7bfef9229f3f2f8f05ab685
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 ["ZP4DXW7F59ZF0J6LD"]', ['ZP4DXW7F59ZF0J6LD'], ['9', False]], ['regression ["1M8GDM9AXKP042788"]', ['1M8GDM9AXKP042788'], ['X', True]], ['partial-repair ["1HGCM82633A004352"]', ['1HGCM82633A004352'], ['3', True]], ['control ["7P852FPZ9AMB30TWM"]', ['7P852FPZ9AMB30TWM'], ['1', False]], ['control ["5E80302J20HS0C2TB"]', ['5E80302J20HS0C2TB'], ['X', False]], ['control ["NRCAB2B221G6DGFEU"]', ['NRCAB2B221G6DGFEU'], ['3', False]], ['control ["802LPLKT5RR2033BP"]', ['802LPLKT5RR2033BP'], ['2', False]], ['control ["G9Y36GVM3T01TBX5P"]', ['G9Y36GVM3T01TBX5P'], ['0', False]]], [['regression ["ZP4DXW7F59ZF0J6LD"]', ['ZP4DXW7F59ZF0J6LD'], ['9', False]], ['regression ["1M8GDM9AXKP042788"]', ['1M8GDM9AXKP042788'], ['X', True]], ['partial-repair ["1HGCM82633A004352"]', ['1HGCM82633A004352'], ['3', True]], ['control ["J5KCLF4060VP1YCZT"]', ['J5KCLF4060VP1YCZT'], ['2', False]], ['control ["7U176LUC2HMRHV49Y"]', ['7U176LUC2HMRHV49Y'], ['0', False]], ['control ["T32AS501XMK3869UE"]', ['T32AS501XMK3869UE'], ['7', False]], ['control ["9D9WJN8Z6UAEAXNMY"]', ['9D9WJN8Z6UAEAXNMY'], ['4', False]], ['control ["G746XY1N49VVXVM2N"]', ['G746XY1N49VVXVM2N'], ['1', False]]], [['regression ["ZP4DXW7F59ZF0J6LD"]', ['ZP4DXW7F59ZF0J6LD'], ['9', False]], ['regression ["1M8GDM9AXKP042788"]', ['1M8GDM9AXKP042788'], ['X', True]], ['partial-repair ["1HGCM82633A004352"]', ['1HGCM82633A004352'], ['3', True]], ['control ["A2C3SUET4AT9FGY0N"]', ['A2C3SUET4AT9FGY0N'], ['5', False]], ['control ["XASS3C3Z3KGD2JETV"]', ['XASS3C3Z3KGD2JETV'], ['8', False]], ['control ["466JDFJ71TZ0MJCXA"]', ['466JDFJ71TZ0MJCXA'], ['X', False]], ['control ["4E2898314S7811191"]', ['4E2898314S7811191'], ['6', False]], ['control ["952403649S86181S3"]', ['952403649S86181S3'], ['1', False]]], [['regression ["ZP4DXW7F59ZF0J6LD"]', ['ZP4DXW7F59ZF0J6LD'], ['9', False]], ['regression ["1M8GDM9AXKP042788"]', ['1M8GDM9AXKP042788'], ['X', True]], ['partial-repair ["1HGCM82633A004352"]', ['1HGCM82633A004352'], ['3', True]], ['control ["F32A05CF4S3S80512"]', ['F32A05CF4S3S80512'], ['1', False]], ['control ["6C2F00FD7S2507305"]', ['6C2F00FD7S2507305'], ['3', False]], ['control ["11111111111111111"]', ['11111111111111111'], ['1', True]], ['control ["1M8GDM9AXKP04278"]', ['1M8GDM9AXKP04278'], 'malformed'], ['control ["1M8GDM9AXKP04278O"]', ['1M8GDM9AXKP04278O'], 'malformed']], [['regression ["ZP4DXW7F59ZF0J6LD"]', ['ZP4DXW7F59ZF0J6LD'], ['9', False]], ['regression ["1M8GDM9AXKP042788"]', ['1M8GDM9AXKP042788'], ['X', True]], ['partial-repair ["1HGCM82633A004352"]', ['1HGCM82633A004352'], ['3', True]], ['control ["1m8gdm9axkp042788"]', ['1m8gdm9axkp042788'], 'malformed'], ['control ["5YJSA1E14HF000001"]', ['5YJSA1E14HF000001'], ['8', False]], ['control ["WVWZZZ1JZ3W386752"]', ['WVWZZZ1JZ3W386752'], ['9', False]], ['control ["SALVA2AE4EH877482"]', ['SALVA2AE4EH877482'], ['7', False]], ['control ["7P852FPZ9AMB30TWM"]', ['7P852FPZ9AMB30TWM'], ['1', 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 ["ZP4DXW7F59ZF0J6LD"] | ['9', False] | ['9', False] | Passed |
| regression ["1M8GDM9AXKP042788"] | ['X', True] | ['X', True] | Passed |
| partial-repair ["1HGCM82633A004352"] | ['3', True] | ['3', True] | Passed |
| control ["7P852FPZ9AMB30TWM"] | ['1', False] | ['1', False] | Passed |
| control ["5E80302J20HS0C2TB"] | ['X', False] | ['X', False] | Passed |
| control ["NRCAB2B221G6DGFEU"] | ['3', False] | ['3', False] | Passed |
| control ["802LPLKT5RR2033BP"] | ['2', False] | ['2', False] | Passed |
| control ["G9Y36GVM3T01TBX5P"] | ['0', False] | ['0', False] | Passed |
SHA-256 / 91056a9bd941a47ee9b58e3418300f37ecfa098be85acbcec5bb060243dd7542
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.159212+00:00.
Case digest / a8c348fb54d70054ff8b2ac2a962a5f52540ba273709af5d1b5531bace6deb83