FA-95861 / Postal address normalization / Open access
Street line standardizer: a direction-named street loses its name to the pre-directional · case 01
"WEST ST" becomes "W ST" although WEST is the street name.
ROOT CAUSE
The leading directional is removed whenever any body token exists, even when it is the last name token left after suffix removal.
VERIFIED REPAIR
Only take a pre-directional when at least one name token remains after it.
Unsuccessful approach: Guarding on the total token count of the whole line still strips WEST from "EAST LANE NORTH"-style lines whose name is a single directional.
Case contract
Input one street line of synthetic text. Uppercase it, delete periods, turn commas into spaces and split on whitespace. The first token is the house number. From the remaining body, in this order: a trailing directional becomes the post-directional only if at least two body tokens exist; then a trailing suffix from the table is abbreviated only if at least two body tokens remain; then a leading directional becomes the pre-directional only if at least one name token would remain. Return number, pre, name, suffix, post joined by single spaces.
Why this case matters
Street lines are the dominant key in address matching; a single-token street named after a direction or suffix must not be abbreviated away.
1 / The failure
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(x):
s = x.upper().replace('.', '').replace(',', ' ')
t = s.split()
if not t:
return ''
num, body = t[0], t[1:]
SUF = {'STREET': 'ST', 'ST': 'ST', 'AVENUE': 'AVE', 'AVE': 'AVE', 'BOULEVARD': 'BLVD', 'BLVD': 'BLVD',
'ROAD': 'RD', 'RD': 'RD', 'LANE': 'LN', 'LN': 'LN', 'COURT': 'CT', 'CT': 'CT'}
DIR = {'NORTH': 'N', 'N': 'N', 'SOUTH': 'S', 'S': 'S', 'EAST': 'E', 'E': 'E', 'WEST': 'W', 'W': 'W'}
pre = suf = post = ''
if len(body) > 1 and body[-1] in DIR:
post = DIR[body[-1]]
body = body[:-1]
if len(body) >= 2 and body[-1] in SUF:
suf = SUF[body[-1]]
body = body[:-1]
if body and body[0] in DIR:
pre = DIR[body[0]]
body = body[1:]
return ' '.join(p for p in [num, pre] + body + [suf, post] if p)
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['mixed-case suffix is abbreviated', '107 Oak Street', '107 OAK ST'], ['periods removed from abbreviations', '107 N. OAK Ave.', '107 N OAK AVE'], ['street named for a direction keeps its name', '107 North', '107 NORTH'], ['two-token body with post-directional', '107 OAK WEST', '107 OAK W'], ['suffix followed by post-directional', '107 OAK ROAD SOUTH', '107 OAK RD S'], ['direction-named street with suffix', '107 WEST ST', '107 WEST ST'], ['direction-named street with suffix and post-directional', '107 EAST LANE NORTH', '107 EAST LN N'], ['comma-separated control', '107 S OAK BOULEVARD,', '107 S OAK BLVD']], [['mixed-case suffix is abbreviated', '114 Elm Street', '114 ELM ST'], ['periods removed from abbreviations', '114 N. ELM Ave.', '114 N ELM AVE'], ['street named for a direction keeps its name', '114 North', '114 NORTH'], ['two-token body with post-directional', '114 ELM WEST', '114 ELM W'], ['suffix followed by post-directional', '114 ELM ROAD SOUTH', '114 ELM RD S'], ['direction-named street with suffix', '114 WEST ST', '114 WEST ST'], ['direction-named street with suffix and post-directional', '114 EAST LANE NORTH', '114 EAST LN N'], ['comma-separated control', '114 S ELM BOULEVARD,', '114 S ELM BLVD']], [['mixed-case suffix is abbreviated', '121 Maple Street', '121 MAPLE ST'], ['periods removed from abbreviations', '121 N. MAPLE Ave.', '121 N MAPLE AVE'], ['street named for a direction keeps its name', '121 North', '121 NORTH'], ['two-token body with post-directional', '121 MAPLE WEST', '121 MAPLE W'], ['suffix followed by post-directional', '121 MAPLE ROAD SOUTH', '121 MAPLE RD S'], ['direction-named street with suffix', '121 WEST ST', '121 WEST ST'], ['direction-named street with suffix and post-directional', '121 EAST LANE NORTH', '121 EAST LN N'], ['comma-separated control', '121 S MAPLE BOULEVARD,', '121 S MAPLE BLVD']], [['mixed-case suffix is abbreviated', '128 Birch Street', '128 BIRCH ST'], ['periods removed from abbreviations', '128 N. BIRCH Ave.', '128 N BIRCH AVE'], ['street named for a direction keeps its name', '128 North', '128 NORTH'], ['two-token body with post-directional', '128 BIRCH WEST', '128 BIRCH W'], ['suffix followed by post-directional', '128 BIRCH ROAD SOUTH', '128 BIRCH RD S'], ['direction-named street with suffix', '128 WEST ST', '128 WEST ST'], ['direction-named street with suffix and post-directional', '128 EAST LANE NORTH', '128 EAST LN N'], ['comma-separated control', '128 S BIRCH BOULEVARD,', '128 S BIRCH BLVD']], [['mixed-case suffix is abbreviated', '135 Cedar Street', '135 CEDAR ST'], ['periods removed from abbreviations', '135 N. CEDAR Ave.', '135 N CEDAR AVE'], ['street named for a direction keeps its name', '135 North', '135 NORTH'], ['two-token body with post-directional', '135 CEDAR WEST', '135 CEDAR W'], ['suffix followed by post-directional', '135 CEDAR ROAD SOUTH', '135 CEDAR RD S'], ['direction-named street with suffix', '135 WEST ST', '135 WEST ST'], ['direction-named street with suffix and post-directional', '135 EAST LANE NORTH', '135 EAST LN N'], ['comma-separated control', '135 S CEDAR BOULEVARD,', '135 S CEDAR BLVD']]]
for label, arg, expected in fixtures[N - 1]:
check(label, solve(arg), 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 |
|---|---|---|---|
| mixed-case suffix is abbreviated | 107 OAK ST | 107 OAK ST | Passed |
| periods removed from abbreviations | 107 N OAK AVE | 107 N OAK AVE | Passed |
| street named for a direction keeps its name | 107 N | 107 NORTH | Failed |
| two-token body with post-directional | 107 OAK W | 107 OAK W | Passed |
| suffix followed by post-directional | 107 OAK RD S | 107 OAK RD S | Passed |
| direction-named street with suffix | 107 W ST | 107 WEST ST | Failed |
| direction-named street with suffix and post-directional | 107 E LN N | 107 EAST LN N | Failed |
| comma-separated control | 107 S OAK BLVD | 107 S OAK BLVD | Passed |
SHA-256 / 3c6eecf6481ef7d22277e514ee107b43b71095c7444339716515ed74e5f69265
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(x):
s = x.upper().replace('.', '').replace(',', ' ')
t = s.split()
if not t:
return ''
num, body = t[0], t[1:]
SUF = {'STREET': 'ST', 'ST': 'ST', 'AVENUE': 'AVE', 'AVE': 'AVE', 'BOULEVARD': 'BLVD', 'BLVD': 'BLVD',
'ROAD': 'RD', 'RD': 'RD', 'LANE': 'LN', 'LN': 'LN', 'COURT': 'CT', 'CT': 'CT'}
DIR = {'NORTH': 'N', 'N': 'N', 'SOUTH': 'S', 'S': 'S', 'EAST': 'E', 'E': 'E', 'WEST': 'W', 'W': 'W'}
pre = suf = post = ''
if len(body) > 1 and body[-1] in DIR:
post = DIR[body[-1]]
body = body[:-1]
if len(body) >= 2 and body[-1] in SUF:
suf = SUF[body[-1]]
body = body[:-1]
if len(t) > 3 and body[0] in DIR:
pre = DIR[body[0]]
body = body[1:]
return ' '.join(p for p in [num, pre] + body + [suf, post] if p)
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['mixed-case suffix is abbreviated', '107 Oak Street', '107 OAK ST'], ['periods removed from abbreviations', '107 N. OAK Ave.', '107 N OAK AVE'], ['street named for a direction keeps its name', '107 North', '107 NORTH'], ['two-token body with post-directional', '107 OAK WEST', '107 OAK W'], ['suffix followed by post-directional', '107 OAK ROAD SOUTH', '107 OAK RD S'], ['direction-named street with suffix', '107 WEST ST', '107 WEST ST'], ['direction-named street with suffix and post-directional', '107 EAST LANE NORTH', '107 EAST LN N'], ['comma-separated control', '107 S OAK BOULEVARD,', '107 S OAK BLVD']], [['mixed-case suffix is abbreviated', '114 Elm Street', '114 ELM ST'], ['periods removed from abbreviations', '114 N. ELM Ave.', '114 N ELM AVE'], ['street named for a direction keeps its name', '114 North', '114 NORTH'], ['two-token body with post-directional', '114 ELM WEST', '114 ELM W'], ['suffix followed by post-directional', '114 ELM ROAD SOUTH', '114 ELM RD S'], ['direction-named street with suffix', '114 WEST ST', '114 WEST ST'], ['direction-named street with suffix and post-directional', '114 EAST LANE NORTH', '114 EAST LN N'], ['comma-separated control', '114 S ELM BOULEVARD,', '114 S ELM BLVD']], [['mixed-case suffix is abbreviated', '121 Maple Street', '121 MAPLE ST'], ['periods removed from abbreviations', '121 N. MAPLE Ave.', '121 N MAPLE AVE'], ['street named for a direction keeps its name', '121 North', '121 NORTH'], ['two-token body with post-directional', '121 MAPLE WEST', '121 MAPLE W'], ['suffix followed by post-directional', '121 MAPLE ROAD SOUTH', '121 MAPLE RD S'], ['direction-named street with suffix', '121 WEST ST', '121 WEST ST'], ['direction-named street with suffix and post-directional', '121 EAST LANE NORTH', '121 EAST LN N'], ['comma-separated control', '121 S MAPLE BOULEVARD,', '121 S MAPLE BLVD']], [['mixed-case suffix is abbreviated', '128 Birch Street', '128 BIRCH ST'], ['periods removed from abbreviations', '128 N. BIRCH Ave.', '128 N BIRCH AVE'], ['street named for a direction keeps its name', '128 North', '128 NORTH'], ['two-token body with post-directional', '128 BIRCH WEST', '128 BIRCH W'], ['suffix followed by post-directional', '128 BIRCH ROAD SOUTH', '128 BIRCH RD S'], ['direction-named street with suffix', '128 WEST ST', '128 WEST ST'], ['direction-named street with suffix and post-directional', '128 EAST LANE NORTH', '128 EAST LN N'], ['comma-separated control', '128 S BIRCH BOULEVARD,', '128 S BIRCH BLVD']], [['mixed-case suffix is abbreviated', '135 Cedar Street', '135 CEDAR ST'], ['periods removed from abbreviations', '135 N. CEDAR Ave.', '135 N CEDAR AVE'], ['street named for a direction keeps its name', '135 North', '135 NORTH'], ['two-token body with post-directional', '135 CEDAR WEST', '135 CEDAR W'], ['suffix followed by post-directional', '135 CEDAR ROAD SOUTH', '135 CEDAR RD S'], ['direction-named street with suffix', '135 WEST ST', '135 WEST ST'], ['direction-named street with suffix and post-directional', '135 EAST LANE NORTH', '135 EAST LN N'], ['comma-separated control', '135 S CEDAR BOULEVARD,', '135 S CEDAR BLVD']]]
for label, arg, expected in fixtures[N - 1]:
check(label, solve(arg), 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 |
|---|---|---|---|
| mixed-case suffix is abbreviated | 107 OAK ST | 107 OAK ST | Passed |
| periods removed from abbreviations | 107 N OAK AVE | 107 N OAK AVE | Passed |
| street named for a direction keeps its name | 107 NORTH | 107 NORTH | Passed |
| two-token body with post-directional | 107 OAK W | 107 OAK W | Passed |
| suffix followed by post-directional | 107 OAK RD S | 107 OAK RD S | Passed |
| direction-named street with suffix | 107 WEST ST | 107 WEST ST | Passed |
| direction-named street with suffix and post-directional | 107 E LN N | 107 EAST LN N | Failed |
| comma-separated control | 107 S OAK BLVD | 107 S OAK BLVD | Passed |
SHA-256 / 6bd14d70ca901fcc8da18f8bff0b9ee71c29c854d83ff26d25349ff748491c93
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(x):
s = x.upper().replace('.', '').replace(',', ' ')
t = s.split()
if not t:
return ''
num, body = t[0], t[1:]
SUF = {'STREET': 'ST', 'ST': 'ST', 'AVENUE': 'AVE', 'AVE': 'AVE', 'BOULEVARD': 'BLVD', 'BLVD': 'BLVD',
'ROAD': 'RD', 'RD': 'RD', 'LANE': 'LN', 'LN': 'LN', 'COURT': 'CT', 'CT': 'CT'}
DIR = {'NORTH': 'N', 'N': 'N', 'SOUTH': 'S', 'S': 'S', 'EAST': 'E', 'E': 'E', 'WEST': 'W', 'W': 'W'}
pre = suf = post = ''
if len(body) > 1 and body[-1] in DIR:
post = DIR[body[-1]]
body = body[:-1]
if len(body) >= 2 and body[-1] in SUF:
suf = SUF[body[-1]]
body = body[:-1]
if body[1:] and body[0] in DIR:
pre = DIR[body[0]]
body = body[1:]
return ' '.join(p for p in [num, pre] + body + [suf, post] if p)
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['mixed-case suffix is abbreviated', '107 Oak Street', '107 OAK ST'], ['periods removed from abbreviations', '107 N. OAK Ave.', '107 N OAK AVE'], ['street named for a direction keeps its name', '107 North', '107 NORTH'], ['two-token body with post-directional', '107 OAK WEST', '107 OAK W'], ['suffix followed by post-directional', '107 OAK ROAD SOUTH', '107 OAK RD S'], ['direction-named street with suffix', '107 WEST ST', '107 WEST ST'], ['direction-named street with suffix and post-directional', '107 EAST LANE NORTH', '107 EAST LN N'], ['comma-separated control', '107 S OAK BOULEVARD,', '107 S OAK BLVD']], [['mixed-case suffix is abbreviated', '114 Elm Street', '114 ELM ST'], ['periods removed from abbreviations', '114 N. ELM Ave.', '114 N ELM AVE'], ['street named for a direction keeps its name', '114 North', '114 NORTH'], ['two-token body with post-directional', '114 ELM WEST', '114 ELM W'], ['suffix followed by post-directional', '114 ELM ROAD SOUTH', '114 ELM RD S'], ['direction-named street with suffix', '114 WEST ST', '114 WEST ST'], ['direction-named street with suffix and post-directional', '114 EAST LANE NORTH', '114 EAST LN N'], ['comma-separated control', '114 S ELM BOULEVARD,', '114 S ELM BLVD']], [['mixed-case suffix is abbreviated', '121 Maple Street', '121 MAPLE ST'], ['periods removed from abbreviations', '121 N. MAPLE Ave.', '121 N MAPLE AVE'], ['street named for a direction keeps its name', '121 North', '121 NORTH'], ['two-token body with post-directional', '121 MAPLE WEST', '121 MAPLE W'], ['suffix followed by post-directional', '121 MAPLE ROAD SOUTH', '121 MAPLE RD S'], ['direction-named street with suffix', '121 WEST ST', '121 WEST ST'], ['direction-named street with suffix and post-directional', '121 EAST LANE NORTH', '121 EAST LN N'], ['comma-separated control', '121 S MAPLE BOULEVARD,', '121 S MAPLE BLVD']], [['mixed-case suffix is abbreviated', '128 Birch Street', '128 BIRCH ST'], ['periods removed from abbreviations', '128 N. BIRCH Ave.', '128 N BIRCH AVE'], ['street named for a direction keeps its name', '128 North', '128 NORTH'], ['two-token body with post-directional', '128 BIRCH WEST', '128 BIRCH W'], ['suffix followed by post-directional', '128 BIRCH ROAD SOUTH', '128 BIRCH RD S'], ['direction-named street with suffix', '128 WEST ST', '128 WEST ST'], ['direction-named street with suffix and post-directional', '128 EAST LANE NORTH', '128 EAST LN N'], ['comma-separated control', '128 S BIRCH BOULEVARD,', '128 S BIRCH BLVD']], [['mixed-case suffix is abbreviated', '135 Cedar Street', '135 CEDAR ST'], ['periods removed from abbreviations', '135 N. CEDAR Ave.', '135 N CEDAR AVE'], ['street named for a direction keeps its name', '135 North', '135 NORTH'], ['two-token body with post-directional', '135 CEDAR WEST', '135 CEDAR W'], ['suffix followed by post-directional', '135 CEDAR ROAD SOUTH', '135 CEDAR RD S'], ['direction-named street with suffix', '135 WEST ST', '135 WEST ST'], ['direction-named street with suffix and post-directional', '135 EAST LANE NORTH', '135 EAST LN N'], ['comma-separated control', '135 S CEDAR BOULEVARD,', '135 S CEDAR BLVD']]]
for label, arg, expected in fixtures[N - 1]:
check(label, solve(arg), 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 |
|---|---|---|---|
| mixed-case suffix is abbreviated | 107 OAK ST | 107 OAK ST | Passed |
| periods removed from abbreviations | 107 N OAK AVE | 107 N OAK AVE | Passed |
| street named for a direction keeps its name | 107 NORTH | 107 NORTH | Passed |
| two-token body with post-directional | 107 OAK W | 107 OAK W | Passed |
| suffix followed by post-directional | 107 OAK RD S | 107 OAK RD S | Passed |
| direction-named street with suffix | 107 WEST ST | 107 WEST ST | Passed |
| direction-named street with suffix and post-directional | 107 EAST LN N | 107 EAST LN N | Passed |
| comma-separated control | 107 S OAK BLVD | 107 S OAK BLVD | Passed |
SHA-256 / 5e3db513a029c237e258c864dba1fe1bf8b1c9eda00c9cbac0c32fd6464ae6dc
Verification & scope
A deterministic toy contract over synthetic, obviously fictitious addresses. The rules are stipulated for this model only and make no claim of conformance with any postal authority standard. 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:52:17.505461+00:00.
Case digest / 3fb359d83feb239ab170e1a1da34d97a4ac9b711ed07fd9053f80769e2663fed