FA-72791 / Check-digit algorithms / Open access
NRIC reads the check table from the other end · case 01
Almost every check letter is wrong.
ROOT CAUSE
The remainder indexes the table as table[10 - r].
VERIFIED REPAIR
Index the table directly with r.
Unsuccessful approach: An off-by-one index table[r - 1] still shifts every letter.
Case contract
Singapore-style NRIC/FIN check letter for the S, T, F and G series: nine characters, series letter, seven digits, check letter (else "malformed"). Weights 2,7,6,5,4,3,2; add 4 for T and G; r = sum mod 11; the letter is "JZIHGFEDCBA"[r] for S/T and "XWUTRQPNMLK"[r] for F/G. Return [expected letter, match].
Why this case matters
Identity verification forms validate NRIC/FIN numbers before submission.
1 / The failure
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(s):
if len(s) != 9 or not s.isascii() or s[0] not in 'STFG' or not s[1:8].isdigit():
return 'malformed'
total = sum(int(ch) * w for ch, w in zip(s[1:8], [2, 7, 6, 5, 4, 3, 2]))
if s[0] in 'TG':
total += 4
r = total % 11
table = 'JZIHGFEDCBA' if s[0] in 'ST' else 'XWUTRQPNMLK'
c = table[10 - r]
return [c, s[8] == c]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression ["S6621805O"]', ['S6621805O'], ['H', False]], ['regression ["G1651468G"]', ['G1651468G'], ['W', False]], ['control ["S123456D"]', ['S123456D'], 'malformed'], ['control ["M1234567K"]', ['M1234567K'], 'malformed'], ['control ["SA234567D"]', ['SA234567D'], 'malformed'], ['control ["G0138893V"]', ['G0138893V'], ['U', False]], ['control ["S3757569X"]', ['S3757569X'], ['J', False]], ['control ["F4116515A"]', ['F4116515A'], ['N', False]]], [['regression ["G0138893V"]', ['G0138893V'], ['U', False]], ['regression ["S3757569X"]', ['S3757569X'], ['J', False]], ['control ["SA234567D"]', ['SA234567D'], 'malformed'], ['control ["S123456D"]', ['S123456D'], 'malformed'], ['control ["M1234567K"]', ['M1234567K'], 'malformed'], ['control ["T4006687X"]', ['T4006687X'], ['F', False]], ['control ["S5101399J"]', ['S5101399J'], ['I', False]], ['control ["S0965290F"]', ['S0965290F'], ['F', True]]], [['regression ["G1812101N"]', ['G1812101N'], ['N', True]], ['regression ["G9259714Y"]', ['G9259714Y'], ['N', False]], ['control ["M1234567K"]', ['M1234567K'], 'malformed'], ['control ["SA234567D"]', ['SA234567D'], 'malformed'], ['control ["S123456D"]', ['S123456D'], 'malformed'], ['control ["G4191951W"]', ['G4191951W'], ['K', False]], ['control ["F9230492U"]', ['F9230492U'], ['L', False]], ['control ["F4160346W"]', ['F4160346W'], ['K', False]]], [['regression ["F3876611S"]', ['F3876611S'], ['L', False]], ['regression ["T7996809P"]', ['T7996809P'], ['E', False]], ['partial-repair ["S5101399J"]', ['S5101399J'], ['I', False]], ['partial-repair ["S0965290F"]', ['S0965290F'], ['F', True]], ['control ["S123456D"]', ['S123456D'], 'malformed'], ['control ["M1234567K"]', ['M1234567K'], 'malformed'], ['control ["SA234567D"]', ['SA234567D'], 'malformed'], ['control ["T2474569W"]', ['T2474569W'], ['J', False]]], [['regression ["F9230492U"]', ['F9230492U'], ['L', False]], ['regression ["F4160346W"]', ['F4160346W'], ['K', False]], ['partial-repair ["T7996809P"]', ['T7996809P'], ['E', False]], ['partial-repair ["G4191951W"]', ['G4191951W'], ['K', False]], ['control ["SA234567D"]', ['SA234567D'], 'malformed'], ['control ["S123456D"]', ['S123456D'], 'malformed'], ['control ["M1234567K"]', ['M1234567K'], 'malformed'], ['control ["F5183813A"]', ['F5183813A'], ['X', 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 ["S6621805O"] | ['D', False] | ['H', False] | Failed |
| regression ["G1651468G"] | ['L', False] | ['W', False] | Failed |
| control ["S123456D"] | malformed | malformed | Passed |
| control ["M1234567K"] | malformed | malformed | Passed |
| control ["SA234567D"] | malformed | malformed | Passed |
| control ["G0138893V"] | ['M', False] | ['U', False] | Failed |
| control ["S3757569X"] | ['A', False] | ['J', False] | Failed |
| control ["F4116515A"] | ['T', False] | ['N', False] | Failed |
SHA-256 / d42cbc750d23cd59408e9dd69675372bc0757ef40f62afc9ce9b6b066da94ec9
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(s):
if len(s) != 9 or not s.isascii() or s[0] not in 'STFG' or not s[1:8].isdigit():
return 'malformed'
total = sum(int(ch) * w for ch, w in zip(s[1:8], [2, 7, 6, 5, 4, 3, 2]))
if s[0] in 'TG':
total += 4
r = total % 11
table = 'JZIHGFEDCBA' if s[0] in 'ST' else 'XWUTRQPNMLK'
c = table[r - 1]
return [c, s[8] == c]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression ["S6621805O"]', ['S6621805O'], ['H', False]], ['regression ["G1651468G"]', ['G1651468G'], ['W', False]], ['control ["S123456D"]', ['S123456D'], 'malformed'], ['control ["M1234567K"]', ['M1234567K'], 'malformed'], ['control ["SA234567D"]', ['SA234567D'], 'malformed'], ['control ["G0138893V"]', ['G0138893V'], ['U', False]], ['control ["S3757569X"]', ['S3757569X'], ['J', False]], ['control ["F4116515A"]', ['F4116515A'], ['N', False]]], [['regression ["G0138893V"]', ['G0138893V'], ['U', False]], ['regression ["S3757569X"]', ['S3757569X'], ['J', False]], ['control ["SA234567D"]', ['SA234567D'], 'malformed'], ['control ["S123456D"]', ['S123456D'], 'malformed'], ['control ["M1234567K"]', ['M1234567K'], 'malformed'], ['control ["T4006687X"]', ['T4006687X'], ['F', False]], ['control ["S5101399J"]', ['S5101399J'], ['I', False]], ['control ["S0965290F"]', ['S0965290F'], ['F', True]]], [['regression ["G1812101N"]', ['G1812101N'], ['N', True]], ['regression ["G9259714Y"]', ['G9259714Y'], ['N', False]], ['control ["M1234567K"]', ['M1234567K'], 'malformed'], ['control ["SA234567D"]', ['SA234567D'], 'malformed'], ['control ["S123456D"]', ['S123456D'], 'malformed'], ['control ["G4191951W"]', ['G4191951W'], ['K', False]], ['control ["F9230492U"]', ['F9230492U'], ['L', False]], ['control ["F4160346W"]', ['F4160346W'], ['K', False]]], [['regression ["F3876611S"]', ['F3876611S'], ['L', False]], ['regression ["T7996809P"]', ['T7996809P'], ['E', False]], ['partial-repair ["S5101399J"]', ['S5101399J'], ['I', False]], ['partial-repair ["S0965290F"]', ['S0965290F'], ['F', True]], ['control ["S123456D"]', ['S123456D'], 'malformed'], ['control ["M1234567K"]', ['M1234567K'], 'malformed'], ['control ["SA234567D"]', ['SA234567D'], 'malformed'], ['control ["T2474569W"]', ['T2474569W'], ['J', False]]], [['regression ["F9230492U"]', ['F9230492U'], ['L', False]], ['regression ["F4160346W"]', ['F4160346W'], ['K', False]], ['partial-repair ["T7996809P"]', ['T7996809P'], ['E', False]], ['partial-repair ["G4191951W"]', ['G4191951W'], ['K', False]], ['control ["SA234567D"]', ['SA234567D'], 'malformed'], ['control ["S123456D"]', ['S123456D'], 'malformed'], ['control ["M1234567K"]', ['M1234567K'], 'malformed'], ['control ["F5183813A"]', ['F5183813A'], ['X', 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 ["S6621805O"] | ['I', False] | ['H', False] | Failed |
| regression ["G1651468G"] | ['X', False] | ['W', False] | Failed |
| control ["S123456D"] | malformed | malformed | Passed |
| control ["M1234567K"] | malformed | malformed | Passed |
| control ["SA234567D"] | malformed | malformed | Passed |
| control ["G0138893V"] | ['W', False] | ['U', False] | Failed |
| control ["S3757569X"] | ['A', False] | ['J', False] | Failed |
| control ["F4116515A"] | ['P', False] | ['N', False] | Failed |
SHA-256 / b6baeb41e1bb0bbdf7f377fbf1024fb276256363122728982ed6193d4e501c18
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(s):
if len(s) != 9 or not s.isascii() or s[0] not in 'STFG' or not s[1:8].isdigit():
return 'malformed'
total = sum(int(ch) * w for ch, w in zip(s[1:8], [2, 7, 6, 5, 4, 3, 2]))
if s[0] in 'TG':
total += 4
r = total % 11
table = 'JZIHGFEDCBA' if s[0] in 'ST' else 'XWUTRQPNMLK'
c = table[r]
return [c, s[8] == c]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression ["S6621805O"]', ['S6621805O'], ['H', False]], ['regression ["G1651468G"]', ['G1651468G'], ['W', False]], ['control ["S123456D"]', ['S123456D'], 'malformed'], ['control ["M1234567K"]', ['M1234567K'], 'malformed'], ['control ["SA234567D"]', ['SA234567D'], 'malformed'], ['control ["G0138893V"]', ['G0138893V'], ['U', False]], ['control ["S3757569X"]', ['S3757569X'], ['J', False]], ['control ["F4116515A"]', ['F4116515A'], ['N', False]]], [['regression ["G0138893V"]', ['G0138893V'], ['U', False]], ['regression ["S3757569X"]', ['S3757569X'], ['J', False]], ['control ["SA234567D"]', ['SA234567D'], 'malformed'], ['control ["S123456D"]', ['S123456D'], 'malformed'], ['control ["M1234567K"]', ['M1234567K'], 'malformed'], ['control ["T4006687X"]', ['T4006687X'], ['F', False]], ['control ["S5101399J"]', ['S5101399J'], ['I', False]], ['control ["S0965290F"]', ['S0965290F'], ['F', True]]], [['regression ["G1812101N"]', ['G1812101N'], ['N', True]], ['regression ["G9259714Y"]', ['G9259714Y'], ['N', False]], ['control ["M1234567K"]', ['M1234567K'], 'malformed'], ['control ["SA234567D"]', ['SA234567D'], 'malformed'], ['control ["S123456D"]', ['S123456D'], 'malformed'], ['control ["G4191951W"]', ['G4191951W'], ['K', False]], ['control ["F9230492U"]', ['F9230492U'], ['L', False]], ['control ["F4160346W"]', ['F4160346W'], ['K', False]]], [['regression ["F3876611S"]', ['F3876611S'], ['L', False]], ['regression ["T7996809P"]', ['T7996809P'], ['E', False]], ['partial-repair ["S5101399J"]', ['S5101399J'], ['I', False]], ['partial-repair ["S0965290F"]', ['S0965290F'], ['F', True]], ['control ["S123456D"]', ['S123456D'], 'malformed'], ['control ["M1234567K"]', ['M1234567K'], 'malformed'], ['control ["SA234567D"]', ['SA234567D'], 'malformed'], ['control ["T2474569W"]', ['T2474569W'], ['J', False]]], [['regression ["F9230492U"]', ['F9230492U'], ['L', False]], ['regression ["F4160346W"]', ['F4160346W'], ['K', False]], ['partial-repair ["T7996809P"]', ['T7996809P'], ['E', False]], ['partial-repair ["G4191951W"]', ['G4191951W'], ['K', False]], ['control ["SA234567D"]', ['SA234567D'], 'malformed'], ['control ["S123456D"]', ['S123456D'], 'malformed'], ['control ["M1234567K"]', ['M1234567K'], 'malformed'], ['control ["F5183813A"]', ['F5183813A'], ['X', 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 ["S6621805O"] | ['H', False] | ['H', False] | Passed |
| regression ["G1651468G"] | ['W', False] | ['W', False] | Passed |
| control ["S123456D"] | malformed | malformed | Passed |
| control ["M1234567K"] | malformed | malformed | Passed |
| control ["SA234567D"] | malformed | malformed | Passed |
| control ["G0138893V"] | ['U', False] | ['U', False] | Passed |
| control ["S3757569X"] | ['J', False] | ['J', False] | Passed |
| control ["F4116515A"] | ['N', False] | ['N', False] | Passed |
SHA-256 / bb2a0cc453315c60431d6101326f038b9c4cc83d7d50b71673635aaf4ca814ea
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:41.628494+00:00.
Case digest / a098911284c9dc34d653d3af453f03eec97bfd2b26f996228b006280623adebe