FA-80386 / Bidirectional text layout / Open access
Weak type resolution: plus sign between numbers · case 01
A plus between Arabic numbers joins them, or European pairs split.
ROOT CAUSE
The W4 ES rule accepts any matching number type instead of European numbers only.
VERIFIED REPAIR
Only turn a single ES between two EN into EN.
Unsuccessful approach: Ignoring the right neighbour joins a number to whatever follows.
Case contract
Input [classes of one isolating run sequence, sos]. W1 NSM takes the previous type (sos at start; ON after LRI/RLI/FSI/PDI). W2 EN after the last strong AL becomes AN. W3 AL->R. W4 a single ES between EN and EN -> EN; a single CS between two numbers of the same type takes that type. W5 a run of ET adjacent to EN -> EN. W6 remaining ES/ET/CS -> ON. W7 EN whose last strong (sos at start) is L -> L. Return resolved classes.
Why this case matters
Mixed right-to-left and left-to-right text must resolve levels and visual order exactly, or words, numbers and carets land in the wrong place.
1 / The failure
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(x):
types, sos = x
t = list(types)
n = len(t)
prev = sos
for i in range(n):
if t[i] == 'NSM':
t[i] = 'ON' if prev in ('LRI', 'RLI', 'FSI', 'PDI') else prev
prev = t[i]
last_strong = sos
for i in range(n):
if t[i] in ('L', 'R', 'AL'):
last_strong = t[i]
elif t[i] == 'EN' and last_strong == 'AL':
t[i] = 'AN'
t = ['R' if c == 'AL' else c for c in t]
for i in range(1, n - 1):
if t[i] == 'ES' and t[i - 1] == t[i + 1] and t[i - 1] in ('EN', 'AN'):
t[i] = 'EN'
elif t[i] == 'CS' and t[i - 1] == t[i + 1] and t[i - 1] in ('EN', 'AN'):
t[i] = t[i - 1]
i = 0
while i < n:
if t[i] == 'ET':
j = i
while j < n and t[j] == 'ET':
j += 1
if (i > 0 and t[i - 1] == 'EN') or (j < n and t[j] == 'EN'):
for k in range(i, j):
t[k] = 'EN'
i = j
else:
i += 1
t = ['ON' if c in ('ES', 'ET', 'CS') else c for c in t]
strong = sos
for i in range(n):
if t[i] in ('L', 'R'):
strong = t[i]
elif t[i] == 'EN' and strong == 'L':
t[i] = 'L'
return t
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('regression: plus sign between numbers', [['L', 'CS', 'AL', 'NSM', 'ET', 'CS', 'AN', 'ES', 'EN'], 'R'], ['L', 'ON', 'R', 'R', 'ON', 'ON', 'AN', 'ON', 'AN']), ('regression: plus sign between numbers', [['ES', 'EN', 'ES', 'WS', 'LRI', 'EN', 'EN', 'LRI', 'AN', 'ES', 'AN'], 'L'], ['ON', 'L', 'ON', 'WS', 'LRI', 'L', 'L', 'LRI', 'AN', 'ON', 'AN']), ('partial-repair probe', [['ES', 'WS', 'CS', 'EN', 'ES', 'CS'], 'R'], ['ON', 'WS', 'ON', 'EN', 'ON', 'ON']), ('partial-repair probe', [['EN', 'ES', 'AL', 'ET', 'ET', 'ON', 'L', 'EN', 'LRI', 'PDI'], 'L'], ['L', 'ON', 'R', 'ON', 'ON', 'ON', 'L', 'L', 'LRI', 'PDI']), ('plus between numbers', [['EN', 'ES', 'EN', 'R'], 'R'], ['EN', 'EN', 'EN', 'R']), ('NSM after isolate initiator', [['LRI', 'NSM', 'L', 'PDI'], 'R'], ['LRI', 'ON', 'L', 'PDI']), ('control layout', [['WS', 'ES'], 'L'], ['WS', 'ON']), ('control layout', [['AN', 'L', 'ES', 'WS', 'AN', 'AL', 'LRI', 'AL', 'NSM', 'ES'], 'L'], ['AN', 'L', 'ON', 'WS', 'AN', 'R', 'LRI', 'R', 'R', 'ON'])], [('regression: plus sign between numbers', [['ES', 'EN', 'ES', 'WS', 'LRI', 'EN', 'EN', 'LRI', 'AN', 'ES', 'AN'], 'L'], ['ON', 'L', 'ON', 'WS', 'LRI', 'L', 'L', 'LRI', 'AN', 'ON', 'AN']), ('regression: plus sign between numbers', [['L', 'CS', 'AL', 'NSM', 'ET', 'CS', 'AN', 'ES', 'EN'], 'R'], ['L', 'ON', 'R', 'R', 'ON', 'ON', 'AN', 'ON', 'AN']), ('partial-repair probe', [['AN', 'L', 'EN', 'ES', 'L'], 'R'], ['AN', 'L', 'L', 'ON', 'L']), ('partial-repair probe', [['ES', 'EN', 'ES', 'AN', 'AL', 'CS', 'ET', 'R', 'AN'], 'R'], ['ON', 'EN', 'ON', 'AN', 'R', 'ON', 'ON', 'R', 'AN']), ('percent after number', [['EN', 'ET', 'ET', 'L'], 'R'], ['EN', 'EN', 'EN', 'L']), ('NSM chain after R', [['R', 'NSM', 'NSM', 'EN'], 'L'], ['R', 'R', 'R', 'EN']), ('control layout', [['AL', 'EN', 'ET', 'L', 'EN', 'CS'], 'L'], ['R', 'AN', 'ON', 'L', 'L', 'ON']), ('control layout', [['NSM', 'R', 'L', 'AL', 'AL'], 'R'], ['R', 'R', 'L', 'R', 'R'])], [('regression: plus sign between numbers', [['L', 'CS', 'AL', 'NSM', 'ET', 'CS', 'AN', 'ES', 'EN'], 'R'], ['L', 'ON', 'R', 'R', 'ON', 'ON', 'AN', 'ON', 'AN']), ('regression: plus sign between numbers', [['ES', 'EN', 'ES', 'WS', 'LRI', 'EN', 'EN', 'LRI', 'AN', 'ES', 'AN'], 'L'], ['ON', 'L', 'ON', 'WS', 'LRI', 'L', 'L', 'LRI', 'AN', 'ON', 'AN']), ('partial-repair probe', [['ET', 'R', 'EN', 'NSM', 'ES', 'AL', 'CS', 'NSM', 'AL'], 'R'], ['ON', 'R', 'EN', 'EN', 'ON', 'R', 'ON', 'ON', 'R']), ('partial-repair probe', [['PDI', 'EN', 'EN', 'NSM', 'ES', 'ET', 'EN'], 'R'], ['PDI', 'EN', 'EN', 'EN', 'ON', 'EN', 'EN']), ('percent after number', [['EN', 'ET', 'ET', 'L'], 'R'], ['EN', 'EN', 'EN', 'L']), ('NSM after isolate initiator', [['LRI', 'NSM', 'L', 'PDI'], 'R'], ['LRI', 'ON', 'L', 'PDI']), ('control layout', [['EN', 'EN', 'NSM'], 'R'], ['EN', 'EN', 'EN']), ('control layout', [['AL', 'ON', 'NSM'], 'R'], ['R', 'ON', 'ON'])], [('regression: plus sign between numbers', [['L', 'CS', 'AL', 'NSM', 'ET', 'CS', 'AN', 'ES', 'EN'], 'R'], ['L', 'ON', 'R', 'R', 'ON', 'ON', 'AN', 'ON', 'AN']), ('regression: plus sign between numbers', [['ES', 'EN', 'ES', 'WS', 'LRI', 'EN', 'EN', 'LRI', 'AN', 'ES', 'AN'], 'L'], ['ON', 'L', 'ON', 'WS', 'LRI', 'L', 'L', 'LRI', 'AN', 'ON', 'AN']), ('partial-repair probe', [['EN', 'ES', 'CS'], 'L'], ['L', 'ON', 'ON']), ('partial-repair probe', [['PDI', 'EN', 'EN', 'NSM', 'ES', 'ET', 'EN'], 'R'], ['PDI', 'EN', 'EN', 'EN', 'ON', 'EN', 'EN']), ('plus between numbers', [['EN', 'ES', 'EN', 'R'], 'R'], ['EN', 'EN', 'EN', 'R']), ('NSM chain after R', [['R', 'NSM', 'NSM', 'EN'], 'L'], ['R', 'R', 'R', 'EN']), ('control layout', [['ET', 'CS', 'ES', 'WS', 'AN', 'CS', 'ES', 'L'], 'L'], ['ON', 'ON', 'ON', 'WS', 'AN', 'ON', 'ON', 'L']), ('control layout', [['EN', 'ET', 'L', 'ES', 'AL', 'AL', 'ES', 'PDI'], 'R'], ['EN', 'EN', 'L', 'ON', 'R', 'R', 'ON', 'PDI'])], [('regression: plus sign between numbers', [['L', 'CS', 'AL', 'NSM', 'ET', 'CS', 'AN', 'ES', 'EN'], 'R'], ['L', 'ON', 'R', 'R', 'ON', 'ON', 'AN', 'ON', 'AN']), ('regression: plus sign between numbers', [['ES', 'EN', 'ES', 'WS', 'LRI', 'EN', 'EN', 'LRI', 'AN', 'ES', 'AN'], 'L'], ['ON', 'L', 'ON', 'WS', 'LRI', 'L', 'L', 'LRI', 'AN', 'ON', 'AN']), ('partial-repair probe', [['ET', 'R', 'EN', 'NSM', 'ES', 'AL', 'CS', 'NSM', 'AL'], 'R'], ['ON', 'R', 'EN', 'EN', 'ON', 'R', 'ON', 'ON', 'R']), ('partial-repair probe', [['AL', 'CS', 'EN', 'EN', 'ES', 'L', 'EN', 'ES', 'L', 'ES'], 'R'], ['R', 'ON', 'AN', 'AN', 'ON', 'L', 'L', 'ON', 'L', 'ON']), ('Arabic number context', [['AL', 'EN', 'CS', 'EN'], 'L'], ['R', 'AN', 'AN', 'AN']), ('plus between numbers', [['EN', 'ES', 'EN', 'R'], 'R'], ['EN', 'EN', 'EN', 'R']), ('control layout', [['AN', 'L', 'EN'], 'R'], ['AN', 'L', 'L']), ('control layout', [['AL', 'AN', 'L', 'LRI', 'ET', 'EN', 'AL', 'L', 'NSM', 'PDI', 'EN'], 'L'], ['R', 'AN', 'L', 'LRI', 'L', 'L', 'R', 'L', 'L', 'PDI', 'L'])]]
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: plus sign between numbers | ['L', 'ON', 'R', 'R', 'ON', 'ON', 'AN', 'EN', 'AN'] | ['L', 'ON', 'R', 'R', 'ON', 'ON', 'AN', 'ON', 'AN'] | Failed |
| regression: plus sign between numbers | ['ON', 'L', 'ON', 'WS', 'LRI', 'L', 'L', 'LRI', 'AN', 'L', 'AN'] | ['ON', 'L', 'ON', 'WS', 'LRI', 'L', 'L', 'LRI', 'AN', 'ON', 'AN'] | Failed |
| partial-repair probe | ['ON', 'WS', 'ON', 'EN', 'ON', 'ON'] | ['ON', 'WS', 'ON', 'EN', 'ON', 'ON'] | Passed |
| partial-repair probe | ['L', 'ON', 'R', 'ON', 'ON', 'ON', 'L', 'L', 'LRI', 'PDI'] | ['L', 'ON', 'R', 'ON', 'ON', 'ON', 'L', 'L', 'LRI', 'PDI'] | Passed |
| plus between numbers | ['EN', 'EN', 'EN', 'R'] | ['EN', 'EN', 'EN', 'R'] | Passed |
| NSM after isolate initiator | ['LRI', 'ON', 'L', 'PDI'] | ['LRI', 'ON', 'L', 'PDI'] | Passed |
| control layout | ['WS', 'ON'] | ['WS', 'ON'] | Passed |
| control layout | ['AN', 'L', 'ON', 'WS', 'AN', 'R', 'LRI', 'R', 'R', 'ON'] | ['AN', 'L', 'ON', 'WS', 'AN', 'R', 'LRI', 'R', 'R', 'ON'] | Passed |
SHA-256 / d344b2a82b306018c3069c5c1154591365c1c2aa1f7555d6006de95193e102b7
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(x):
types, sos = x
t = list(types)
n = len(t)
prev = sos
for i in range(n):
if t[i] == 'NSM':
t[i] = 'ON' if prev in ('LRI', 'RLI', 'FSI', 'PDI') else prev
prev = t[i]
last_strong = sos
for i in range(n):
if t[i] in ('L', 'R', 'AL'):
last_strong = t[i]
elif t[i] == 'EN' and last_strong == 'AL':
t[i] = 'AN'
t = ['R' if c == 'AL' else c for c in t]
for i in range(1, n - 1):
if t[i] == 'ES' and t[i - 1] == 'EN':
t[i] = 'EN'
elif t[i] == 'CS' and t[i - 1] == t[i + 1] and t[i - 1] in ('EN', 'AN'):
t[i] = t[i - 1]
i = 0
while i < n:
if t[i] == 'ET':
j = i
while j < n and t[j] == 'ET':
j += 1
if (i > 0 and t[i - 1] == 'EN') or (j < n and t[j] == 'EN'):
for k in range(i, j):
t[k] = 'EN'
i = j
else:
i += 1
t = ['ON' if c in ('ES', 'ET', 'CS') else c for c in t]
strong = sos
for i in range(n):
if t[i] in ('L', 'R'):
strong = t[i]
elif t[i] == 'EN' and strong == 'L':
t[i] = 'L'
return t
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('regression: plus sign between numbers', [['L', 'CS', 'AL', 'NSM', 'ET', 'CS', 'AN', 'ES', 'EN'], 'R'], ['L', 'ON', 'R', 'R', 'ON', 'ON', 'AN', 'ON', 'AN']), ('regression: plus sign between numbers', [['ES', 'EN', 'ES', 'WS', 'LRI', 'EN', 'EN', 'LRI', 'AN', 'ES', 'AN'], 'L'], ['ON', 'L', 'ON', 'WS', 'LRI', 'L', 'L', 'LRI', 'AN', 'ON', 'AN']), ('partial-repair probe', [['ES', 'WS', 'CS', 'EN', 'ES', 'CS'], 'R'], ['ON', 'WS', 'ON', 'EN', 'ON', 'ON']), ('partial-repair probe', [['EN', 'ES', 'AL', 'ET', 'ET', 'ON', 'L', 'EN', 'LRI', 'PDI'], 'L'], ['L', 'ON', 'R', 'ON', 'ON', 'ON', 'L', 'L', 'LRI', 'PDI']), ('plus between numbers', [['EN', 'ES', 'EN', 'R'], 'R'], ['EN', 'EN', 'EN', 'R']), ('NSM after isolate initiator', [['LRI', 'NSM', 'L', 'PDI'], 'R'], ['LRI', 'ON', 'L', 'PDI']), ('control layout', [['WS', 'ES'], 'L'], ['WS', 'ON']), ('control layout', [['AN', 'L', 'ES', 'WS', 'AN', 'AL', 'LRI', 'AL', 'NSM', 'ES'], 'L'], ['AN', 'L', 'ON', 'WS', 'AN', 'R', 'LRI', 'R', 'R', 'ON'])], [('regression: plus sign between numbers', [['ES', 'EN', 'ES', 'WS', 'LRI', 'EN', 'EN', 'LRI', 'AN', 'ES', 'AN'], 'L'], ['ON', 'L', 'ON', 'WS', 'LRI', 'L', 'L', 'LRI', 'AN', 'ON', 'AN']), ('regression: plus sign between numbers', [['L', 'CS', 'AL', 'NSM', 'ET', 'CS', 'AN', 'ES', 'EN'], 'R'], ['L', 'ON', 'R', 'R', 'ON', 'ON', 'AN', 'ON', 'AN']), ('partial-repair probe', [['AN', 'L', 'EN', 'ES', 'L'], 'R'], ['AN', 'L', 'L', 'ON', 'L']), ('partial-repair probe', [['ES', 'EN', 'ES', 'AN', 'AL', 'CS', 'ET', 'R', 'AN'], 'R'], ['ON', 'EN', 'ON', 'AN', 'R', 'ON', 'ON', 'R', 'AN']), ('percent after number', [['EN', 'ET', 'ET', 'L'], 'R'], ['EN', 'EN', 'EN', 'L']), ('NSM chain after R', [['R', 'NSM', 'NSM', 'EN'], 'L'], ['R', 'R', 'R', 'EN']), ('control layout', [['AL', 'EN', 'ET', 'L', 'EN', 'CS'], 'L'], ['R', 'AN', 'ON', 'L', 'L', 'ON']), ('control layout', [['NSM', 'R', 'L', 'AL', 'AL'], 'R'], ['R', 'R', 'L', 'R', 'R'])], [('regression: plus sign between numbers', [['L', 'CS', 'AL', 'NSM', 'ET', 'CS', 'AN', 'ES', 'EN'], 'R'], ['L', 'ON', 'R', 'R', 'ON', 'ON', 'AN', 'ON', 'AN']), ('regression: plus sign between numbers', [['ES', 'EN', 'ES', 'WS', 'LRI', 'EN', 'EN', 'LRI', 'AN', 'ES', 'AN'], 'L'], ['ON', 'L', 'ON', 'WS', 'LRI', 'L', 'L', 'LRI', 'AN', 'ON', 'AN']), ('partial-repair probe', [['ET', 'R', 'EN', 'NSM', 'ES', 'AL', 'CS', 'NSM', 'AL'], 'R'], ['ON', 'R', 'EN', 'EN', 'ON', 'R', 'ON', 'ON', 'R']), ('partial-repair probe', [['PDI', 'EN', 'EN', 'NSM', 'ES', 'ET', 'EN'], 'R'], ['PDI', 'EN', 'EN', 'EN', 'ON', 'EN', 'EN']), ('percent after number', [['EN', 'ET', 'ET', 'L'], 'R'], ['EN', 'EN', 'EN', 'L']), ('NSM after isolate initiator', [['LRI', 'NSM', 'L', 'PDI'], 'R'], ['LRI', 'ON', 'L', 'PDI']), ('control layout', [['EN', 'EN', 'NSM'], 'R'], ['EN', 'EN', 'EN']), ('control layout', [['AL', 'ON', 'NSM'], 'R'], ['R', 'ON', 'ON'])], [('regression: plus sign between numbers', [['L', 'CS', 'AL', 'NSM', 'ET', 'CS', 'AN', 'ES', 'EN'], 'R'], ['L', 'ON', 'R', 'R', 'ON', 'ON', 'AN', 'ON', 'AN']), ('regression: plus sign between numbers', [['ES', 'EN', 'ES', 'WS', 'LRI', 'EN', 'EN', 'LRI', 'AN', 'ES', 'AN'], 'L'], ['ON', 'L', 'ON', 'WS', 'LRI', 'L', 'L', 'LRI', 'AN', 'ON', 'AN']), ('partial-repair probe', [['EN', 'ES', 'CS'], 'L'], ['L', 'ON', 'ON']), ('partial-repair probe', [['PDI', 'EN', 'EN', 'NSM', 'ES', 'ET', 'EN'], 'R'], ['PDI', 'EN', 'EN', 'EN', 'ON', 'EN', 'EN']), ('plus between numbers', [['EN', 'ES', 'EN', 'R'], 'R'], ['EN', 'EN', 'EN', 'R']), ('NSM chain after R', [['R', 'NSM', 'NSM', 'EN'], 'L'], ['R', 'R', 'R', 'EN']), ('control layout', [['ET', 'CS', 'ES', 'WS', 'AN', 'CS', 'ES', 'L'], 'L'], ['ON', 'ON', 'ON', 'WS', 'AN', 'ON', 'ON', 'L']), ('control layout', [['EN', 'ET', 'L', 'ES', 'AL', 'AL', 'ES', 'PDI'], 'R'], ['EN', 'EN', 'L', 'ON', 'R', 'R', 'ON', 'PDI'])], [('regression: plus sign between numbers', [['L', 'CS', 'AL', 'NSM', 'ET', 'CS', 'AN', 'ES', 'EN'], 'R'], ['L', 'ON', 'R', 'R', 'ON', 'ON', 'AN', 'ON', 'AN']), ('regression: plus sign between numbers', [['ES', 'EN', 'ES', 'WS', 'LRI', 'EN', 'EN', 'LRI', 'AN', 'ES', 'AN'], 'L'], ['ON', 'L', 'ON', 'WS', 'LRI', 'L', 'L', 'LRI', 'AN', 'ON', 'AN']), ('partial-repair probe', [['ET', 'R', 'EN', 'NSM', 'ES', 'AL', 'CS', 'NSM', 'AL'], 'R'], ['ON', 'R', 'EN', 'EN', 'ON', 'R', 'ON', 'ON', 'R']), ('partial-repair probe', [['AL', 'CS', 'EN', 'EN', 'ES', 'L', 'EN', 'ES', 'L', 'ES'], 'R'], ['R', 'ON', 'AN', 'AN', 'ON', 'L', 'L', 'ON', 'L', 'ON']), ('Arabic number context', [['AL', 'EN', 'CS', 'EN'], 'L'], ['R', 'AN', 'AN', 'AN']), ('plus between numbers', [['EN', 'ES', 'EN', 'R'], 'R'], ['EN', 'EN', 'EN', 'R']), ('control layout', [['AN', 'L', 'EN'], 'R'], ['AN', 'L', 'L']), ('control layout', [['AL', 'AN', 'L', 'LRI', 'ET', 'EN', 'AL', 'L', 'NSM', 'PDI', 'EN'], 'L'], ['R', 'AN', 'L', 'LRI', 'L', 'L', 'R', 'L', 'L', 'PDI', 'L'])]]
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: plus sign between numbers | ['L', 'ON', 'R', 'R', 'ON', 'ON', 'AN', 'ON', 'AN'] | ['L', 'ON', 'R', 'R', 'ON', 'ON', 'AN', 'ON', 'AN'] | Passed |
| regression: plus sign between numbers | ['ON', 'L', 'L', 'WS', 'LRI', 'L', 'L', 'LRI', 'AN', 'ON', 'AN'] | ['ON', 'L', 'ON', 'WS', 'LRI', 'L', 'L', 'LRI', 'AN', 'ON', 'AN'] | Failed |
| partial-repair probe | ['ON', 'WS', 'ON', 'EN', 'EN', 'ON'] | ['ON', 'WS', 'ON', 'EN', 'ON', 'ON'] | Failed |
| partial-repair probe | ['L', 'L', 'R', 'ON', 'ON', 'ON', 'L', 'L', 'LRI', 'PDI'] | ['L', 'ON', 'R', 'ON', 'ON', 'ON', 'L', 'L', 'LRI', 'PDI'] | Failed |
| plus between numbers | ['EN', 'EN', 'EN', 'R'] | ['EN', 'EN', 'EN', 'R'] | Passed |
| NSM after isolate initiator | ['LRI', 'ON', 'L', 'PDI'] | ['LRI', 'ON', 'L', 'PDI'] | Passed |
| control layout | ['WS', 'ON'] | ['WS', 'ON'] | Passed |
| control layout | ['AN', 'L', 'ON', 'WS', 'AN', 'R', 'LRI', 'R', 'R', 'ON'] | ['AN', 'L', 'ON', 'WS', 'AN', 'R', 'LRI', 'R', 'R', 'ON'] | Passed |
SHA-256 / 442ea5c2d9d5eb654d39fb897d4c6074f0f71610a9fc1656f6abbbde1c3365e3
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(x):
types, sos = x
t = list(types)
n = len(t)
prev = sos
for i in range(n):
if t[i] == 'NSM':
t[i] = 'ON' if prev in ('LRI', 'RLI', 'FSI', 'PDI') else prev
prev = t[i]
last_strong = sos
for i in range(n):
if t[i] in ('L', 'R', 'AL'):
last_strong = t[i]
elif t[i] == 'EN' and last_strong == 'AL':
t[i] = 'AN'
t = ['R' if c == 'AL' else c for c in t]
for i in range(1, n - 1):
if t[i] == 'ES' and t[i - 1] == 'EN' and t[i + 1] == 'EN':
t[i] = 'EN'
elif t[i] == 'CS' and t[i - 1] == t[i + 1] and t[i - 1] in ('EN', 'AN'):
t[i] = t[i - 1]
i = 0
while i < n:
if t[i] == 'ET':
j = i
while j < n and t[j] == 'ET':
j += 1
if (i > 0 and t[i - 1] == 'EN') or (j < n and t[j] == 'EN'):
for k in range(i, j):
t[k] = 'EN'
i = j
else:
i += 1
t = ['ON' if c in ('ES', 'ET', 'CS') else c for c in t]
strong = sos
for i in range(n):
if t[i] in ('L', 'R'):
strong = t[i]
elif t[i] == 'EN' and strong == 'L':
t[i] = 'L'
return t
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('regression: plus sign between numbers', [['L', 'CS', 'AL', 'NSM', 'ET', 'CS', 'AN', 'ES', 'EN'], 'R'], ['L', 'ON', 'R', 'R', 'ON', 'ON', 'AN', 'ON', 'AN']), ('regression: plus sign between numbers', [['ES', 'EN', 'ES', 'WS', 'LRI', 'EN', 'EN', 'LRI', 'AN', 'ES', 'AN'], 'L'], ['ON', 'L', 'ON', 'WS', 'LRI', 'L', 'L', 'LRI', 'AN', 'ON', 'AN']), ('partial-repair probe', [['ES', 'WS', 'CS', 'EN', 'ES', 'CS'], 'R'], ['ON', 'WS', 'ON', 'EN', 'ON', 'ON']), ('partial-repair probe', [['EN', 'ES', 'AL', 'ET', 'ET', 'ON', 'L', 'EN', 'LRI', 'PDI'], 'L'], ['L', 'ON', 'R', 'ON', 'ON', 'ON', 'L', 'L', 'LRI', 'PDI']), ('plus between numbers', [['EN', 'ES', 'EN', 'R'], 'R'], ['EN', 'EN', 'EN', 'R']), ('NSM after isolate initiator', [['LRI', 'NSM', 'L', 'PDI'], 'R'], ['LRI', 'ON', 'L', 'PDI']), ('control layout', [['WS', 'ES'], 'L'], ['WS', 'ON']), ('control layout', [['AN', 'L', 'ES', 'WS', 'AN', 'AL', 'LRI', 'AL', 'NSM', 'ES'], 'L'], ['AN', 'L', 'ON', 'WS', 'AN', 'R', 'LRI', 'R', 'R', 'ON'])], [('regression: plus sign between numbers', [['ES', 'EN', 'ES', 'WS', 'LRI', 'EN', 'EN', 'LRI', 'AN', 'ES', 'AN'], 'L'], ['ON', 'L', 'ON', 'WS', 'LRI', 'L', 'L', 'LRI', 'AN', 'ON', 'AN']), ('regression: plus sign between numbers', [['L', 'CS', 'AL', 'NSM', 'ET', 'CS', 'AN', 'ES', 'EN'], 'R'], ['L', 'ON', 'R', 'R', 'ON', 'ON', 'AN', 'ON', 'AN']), ('partial-repair probe', [['AN', 'L', 'EN', 'ES', 'L'], 'R'], ['AN', 'L', 'L', 'ON', 'L']), ('partial-repair probe', [['ES', 'EN', 'ES', 'AN', 'AL', 'CS', 'ET', 'R', 'AN'], 'R'], ['ON', 'EN', 'ON', 'AN', 'R', 'ON', 'ON', 'R', 'AN']), ('percent after number', [['EN', 'ET', 'ET', 'L'], 'R'], ['EN', 'EN', 'EN', 'L']), ('NSM chain after R', [['R', 'NSM', 'NSM', 'EN'], 'L'], ['R', 'R', 'R', 'EN']), ('control layout', [['AL', 'EN', 'ET', 'L', 'EN', 'CS'], 'L'], ['R', 'AN', 'ON', 'L', 'L', 'ON']), ('control layout', [['NSM', 'R', 'L', 'AL', 'AL'], 'R'], ['R', 'R', 'L', 'R', 'R'])], [('regression: plus sign between numbers', [['L', 'CS', 'AL', 'NSM', 'ET', 'CS', 'AN', 'ES', 'EN'], 'R'], ['L', 'ON', 'R', 'R', 'ON', 'ON', 'AN', 'ON', 'AN']), ('regression: plus sign between numbers', [['ES', 'EN', 'ES', 'WS', 'LRI', 'EN', 'EN', 'LRI', 'AN', 'ES', 'AN'], 'L'], ['ON', 'L', 'ON', 'WS', 'LRI', 'L', 'L', 'LRI', 'AN', 'ON', 'AN']), ('partial-repair probe', [['ET', 'R', 'EN', 'NSM', 'ES', 'AL', 'CS', 'NSM', 'AL'], 'R'], ['ON', 'R', 'EN', 'EN', 'ON', 'R', 'ON', 'ON', 'R']), ('partial-repair probe', [['PDI', 'EN', 'EN', 'NSM', 'ES', 'ET', 'EN'], 'R'], ['PDI', 'EN', 'EN', 'EN', 'ON', 'EN', 'EN']), ('percent after number', [['EN', 'ET', 'ET', 'L'], 'R'], ['EN', 'EN', 'EN', 'L']), ('NSM after isolate initiator', [['LRI', 'NSM', 'L', 'PDI'], 'R'], ['LRI', 'ON', 'L', 'PDI']), ('control layout', [['EN', 'EN', 'NSM'], 'R'], ['EN', 'EN', 'EN']), ('control layout', [['AL', 'ON', 'NSM'], 'R'], ['R', 'ON', 'ON'])], [('regression: plus sign between numbers', [['L', 'CS', 'AL', 'NSM', 'ET', 'CS', 'AN', 'ES', 'EN'], 'R'], ['L', 'ON', 'R', 'R', 'ON', 'ON', 'AN', 'ON', 'AN']), ('regression: plus sign between numbers', [['ES', 'EN', 'ES', 'WS', 'LRI', 'EN', 'EN', 'LRI', 'AN', 'ES', 'AN'], 'L'], ['ON', 'L', 'ON', 'WS', 'LRI', 'L', 'L', 'LRI', 'AN', 'ON', 'AN']), ('partial-repair probe', [['EN', 'ES', 'CS'], 'L'], ['L', 'ON', 'ON']), ('partial-repair probe', [['PDI', 'EN', 'EN', 'NSM', 'ES', 'ET', 'EN'], 'R'], ['PDI', 'EN', 'EN', 'EN', 'ON', 'EN', 'EN']), ('plus between numbers', [['EN', 'ES', 'EN', 'R'], 'R'], ['EN', 'EN', 'EN', 'R']), ('NSM chain after R', [['R', 'NSM', 'NSM', 'EN'], 'L'], ['R', 'R', 'R', 'EN']), ('control layout', [['ET', 'CS', 'ES', 'WS', 'AN', 'CS', 'ES', 'L'], 'L'], ['ON', 'ON', 'ON', 'WS', 'AN', 'ON', 'ON', 'L']), ('control layout', [['EN', 'ET', 'L', 'ES', 'AL', 'AL', 'ES', 'PDI'], 'R'], ['EN', 'EN', 'L', 'ON', 'R', 'R', 'ON', 'PDI'])], [('regression: plus sign between numbers', [['L', 'CS', 'AL', 'NSM', 'ET', 'CS', 'AN', 'ES', 'EN'], 'R'], ['L', 'ON', 'R', 'R', 'ON', 'ON', 'AN', 'ON', 'AN']), ('regression: plus sign between numbers', [['ES', 'EN', 'ES', 'WS', 'LRI', 'EN', 'EN', 'LRI', 'AN', 'ES', 'AN'], 'L'], ['ON', 'L', 'ON', 'WS', 'LRI', 'L', 'L', 'LRI', 'AN', 'ON', 'AN']), ('partial-repair probe', [['ET', 'R', 'EN', 'NSM', 'ES', 'AL', 'CS', 'NSM', 'AL'], 'R'], ['ON', 'R', 'EN', 'EN', 'ON', 'R', 'ON', 'ON', 'R']), ('partial-repair probe', [['AL', 'CS', 'EN', 'EN', 'ES', 'L', 'EN', 'ES', 'L', 'ES'], 'R'], ['R', 'ON', 'AN', 'AN', 'ON', 'L', 'L', 'ON', 'L', 'ON']), ('Arabic number context', [['AL', 'EN', 'CS', 'EN'], 'L'], ['R', 'AN', 'AN', 'AN']), ('plus between numbers', [['EN', 'ES', 'EN', 'R'], 'R'], ['EN', 'EN', 'EN', 'R']), ('control layout', [['AN', 'L', 'EN'], 'R'], ['AN', 'L', 'L']), ('control layout', [['AL', 'AN', 'L', 'LRI', 'ET', 'EN', 'AL', 'L', 'NSM', 'PDI', 'EN'], 'L'], ['R', 'AN', 'L', 'LRI', 'L', 'L', 'R', 'L', 'L', 'PDI', 'L'])]]
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: plus sign between numbers | ['L', 'ON', 'R', 'R', 'ON', 'ON', 'AN', 'ON', 'AN'] | ['L', 'ON', 'R', 'R', 'ON', 'ON', 'AN', 'ON', 'AN'] | Passed |
| regression: plus sign between numbers | ['ON', 'L', 'ON', 'WS', 'LRI', 'L', 'L', 'LRI', 'AN', 'ON', 'AN'] | ['ON', 'L', 'ON', 'WS', 'LRI', 'L', 'L', 'LRI', 'AN', 'ON', 'AN'] | Passed |
| partial-repair probe | ['ON', 'WS', 'ON', 'EN', 'ON', 'ON'] | ['ON', 'WS', 'ON', 'EN', 'ON', 'ON'] | Passed |
| partial-repair probe | ['L', 'ON', 'R', 'ON', 'ON', 'ON', 'L', 'L', 'LRI', 'PDI'] | ['L', 'ON', 'R', 'ON', 'ON', 'ON', 'L', 'L', 'LRI', 'PDI'] | Passed |
| plus between numbers | ['EN', 'EN', 'EN', 'R'] | ['EN', 'EN', 'EN', 'R'] | Passed |
| NSM after isolate initiator | ['LRI', 'ON', 'L', 'PDI'] | ['LRI', 'ON', 'L', 'PDI'] | Passed |
| control layout | ['WS', 'ON'] | ['WS', 'ON'] | Passed |
| control layout | ['AN', 'L', 'ON', 'WS', 'AN', 'R', 'LRI', 'R', 'R', 'ON'] | ['AN', 'L', 'ON', 'WS', 'AN', 'R', 'LRI', 'R', 'R', 'ON'] | Passed |
SHA-256 / 54e121bcd84d518684992d7e6029495fb0b9e8f8012f0f41b0a222d495374fcf
Verification & scope
A deterministic toy bidi model over stipulated class labels and integer levels; it is inspired by, but does not claim conformance to, any published algorithm. 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:49:53.486078+00:00.
Case digest / 0776d35828d559994400391be4161ae63a7097b099b92912e688a7dc80bf670f