FAILURE MAP
← Case archive

FA-80681 / Bidirectional text layout / Open access

Bidi selection highlight: logical to visual mapping · case 01

Highlights follow the logical range as if the line were unidirectional.

Verified by executionVariant 1 · 8 checks per implementationDownload source bundle ↓JSON ↗

ROOT CAUSE

The logical offsets are used directly as visual slots.

VERIFIED REPAIR

Map each selected logical index through the visual position table.

Unsuccessful approach: Indexing the visual order array with logical indices applies the wrong permutation direction.

Case contract

Input [levels, anchor, focus]. The logical selection covers characters min..max-1. Each selected character occupies its unit visual slot (level reversal); merge adjacent slots into [x0, x1) rectangles sorted by x. Return the rectangles.

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):
    def reorder(lv):
        vis = list(range(len(lv)))
        odd = [l for l in lv if l % 2 == 1]
        if not odd:
            return vis
        for lev in range(max(lv), min(odd) - 1, -1):
            i = 0
            while i < len(vis):
                if lv[vis[i]] >= lev:
                    j = i
                    while j < len(vis) and lv[vis[j]] >= lev:
                        j += 1
                    vis[i:j] = vis[i:j][::-1]
                    i = j
                else:
                    i += 1
        return vis
    
    levels, a, b = x
    a, b = min(a, b), max(a, b)
    vis = reorder(levels)
    pos = [0] * len(levels)
    for v, i in enumerate(vis):
        pos[i] = v
    sel = list(range(a, b))
    rects = []
    for p in sel:
        if rects and rects[-1][1] == p:
            rects[-1][1] = p + 1
        else:
            rects.append([p, p + 1])
    return rects
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('backward selection', [[1, 1, 1], 3, 1], [[0, 2]]), ('regression: logical to visual mapping', [[4, 4, 2, 4, 1], 4, 2], [[3, 5]]), ('regression: logical to visual mapping', [[1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 1], 6, 3], [[5, 8]]), ('regression: logical to visual mapping', [[4, 4, 4, 1], 2, 3], [[3, 4]]), ('selection crossing direction change', [[0, 0, 1, 1, 0], 1, 4], [[1, 4]]), ('control layout', [[3, 3, 3, 3, 3, 3, 3, 3, 0, 3, 3], 10, 10], []), ('control layout', [[3, 2, 2, 2, 2, 2], 2, 4], [[2, 4]]), ('control layout', [[2, 2, 3, 3, 2, 2, 0, 0], 8, 2], [[2, 8]])], [('regression: logical to visual mapping', [[2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 0], 12, 9], [[0, 2], [11, 12]]), ('regression: logical to visual mapping', [[1, 0, 1, 2, 2, 2, 3, 2, 1, 1, 3], 9, 4], [[4, 5], [6, 10]]), ('regression: logical to visual mapping', [[4, 4, 2, 2, 1, 1, 1, 1, 1, 1], 7, 0], [[3, 10]]), ('regression: logical to visual mapping', [[2, 2, 2, 2, 1, 1, 1], 0, 1], [[3, 4]]), ('backward selection', [[1, 1, 1], 3, 1], [[0, 2]]), ('selection crossing direction change', [[0, 0, 1, 1, 0], 1, 4], [[1, 4]]), ('control layout', [[2, 3, 3, 3, 3, 3, 0, 0, 0, 2, 2], 6, 9], [[6, 9]]), ('control layout', [[2, 3, 3], 3, 3], [])], [('regression: logical to visual mapping', [[3, 3, 3, 3, 1], 4, 5], [[0, 1]]), ('regression: logical to visual mapping', [[1, 1, 1, 2], 3, 0], [[1, 4]]), ('regression: logical to visual mapping', [[1, 1, 1, 3, 2, 2, 2, 2, 4, 4], 2, 6], [[0, 3], [7, 8]]), ('regression: logical to visual mapping', [[2, 2, 2, 2, 2, 2, 1, 1, 1], 2, 1], [[4, 5]]), ('selection crossing direction change', [[0, 0, 1, 1, 0], 1, 4], [[1, 4]]), ('backward selection', [[1, 1, 1], 3, 1], [[0, 2]]), ('control layout', [[2, 2], 2, 1], [[1, 2]]), ('control layout', [[0, 0, 0, 0, 0, 1, 1, 1], 4, 2], [[2, 4]])], [('regression: logical to visual mapping', [[3, 3], 1, 0], [[1, 2]]), ('regression: logical to visual mapping', [[2, 2, 2, 1, 4, 4], 4, 3], [[2, 3]]), ('regression: logical to visual mapping', [[1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 1], 6, 3], [[5, 8]]), ('regression: logical to visual mapping', [[1, 4, 4, 4, 4, 4, 4, 1, 1, 2], 10, 5], [[0, 3], [7, 9]]), ('selection crossing direction change', [[0, 0, 1, 1, 0], 1, 4], [[1, 4]]), ('backward selection', [[1, 1, 1], 3, 1], [[0, 2]]), ('control layout', [[1, 0, 0, 1, 1], 2, 0], [[0, 2]]), ('control layout', [[2, 1, 1, 1, 1, 1, 4], 7, 0], [[0, 7]])], [('regression: logical to visual mapping', [[2, 2, 2, 2, 2, 2, 1, 1], 0, 3], [[2, 5]]), ('regression: logical to visual mapping', [[2, 4, 1, 1, 1, 1, 1], 6, 1], [[1, 5], [6, 7]]), ('regression: logical to visual mapping', [[4, 4, 4, 4, 4, 4, 1, 1, 1, 2, 2], 9, 1], [[2, 5], [6, 11]]), ('regression: logical to visual mapping', [[2, 1, 1, 1, 1, 1, 1, 1, 2, 4, 4], 7, 10], [[0, 2], [3, 4]]), ('backward selection', [[1, 1, 1], 3, 1], [[0, 2]]), ('selection crossing direction change', [[0, 0, 1, 1, 0], 1, 4], [[1, 4]]), ('control layout', [[2, 2, 2, 2, 2, 4], 2, 0], [[0, 2]]), ('control layout', [[1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1], 10, 10], [])]]
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 fixtureActualExpectedOutcome
backward selection[[1, 3]][[0, 2]]Failed
regression: logical to visual mapping[[2, 4]][[3, 5]]Failed
regression: logical to visual mapping[[3, 6]][[5, 8]]Failed
regression: logical to visual mapping[[2, 3]][[3, 4]]Failed
selection crossing direction change[[1, 4]][[1, 4]]Passed
control layout[][]Passed
control layout[[2, 4]][[2, 4]]Passed
control layout[[2, 8]][[2, 8]]Passed

SHA-256 / 43e42d599ac3b2e6930d493b4c25df3e9c3afa338668bc4d884e30dd2e72e8b8

2 / The unsuccessful fix

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(x):
    def reorder(lv):
        vis = list(range(len(lv)))
        odd = [l for l in lv if l % 2 == 1]
        if not odd:
            return vis
        for lev in range(max(lv), min(odd) - 1, -1):
            i = 0
            while i < len(vis):
                if lv[vis[i]] >= lev:
                    j = i
                    while j < len(vis) and lv[vis[j]] >= lev:
                        j += 1
                    vis[i:j] = vis[i:j][::-1]
                    i = j
                else:
                    i += 1
        return vis
    
    levels, a, b = x
    a, b = min(a, b), max(a, b)
    vis = reorder(levels)
    pos = [0] * len(levels)
    for v, i in enumerate(vis):
        pos[i] = v
    sel = sorted(vis[i] for i in range(a, b))
    rects = []
    for p in sel:
        if rects and rects[-1][1] == p:
            rects[-1][1] = p + 1
        else:
            rects.append([p, p + 1])
    return rects
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('backward selection', [[1, 1, 1], 3, 1], [[0, 2]]), ('regression: logical to visual mapping', [[4, 4, 2, 4, 1], 4, 2], [[3, 5]]), ('regression: logical to visual mapping', [[1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 1], 6, 3], [[5, 8]]), ('regression: logical to visual mapping', [[4, 4, 4, 1], 2, 3], [[3, 4]]), ('selection crossing direction change', [[0, 0, 1, 1, 0], 1, 4], [[1, 4]]), ('control layout', [[3, 3, 3, 3, 3, 3, 3, 3, 0, 3, 3], 10, 10], []), ('control layout', [[3, 2, 2, 2, 2, 2], 2, 4], [[2, 4]]), ('control layout', [[2, 2, 3, 3, 2, 2, 0, 0], 8, 2], [[2, 8]])], [('regression: logical to visual mapping', [[2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 0], 12, 9], [[0, 2], [11, 12]]), ('regression: logical to visual mapping', [[1, 0, 1, 2, 2, 2, 3, 2, 1, 1, 3], 9, 4], [[4, 5], [6, 10]]), ('regression: logical to visual mapping', [[4, 4, 2, 2, 1, 1, 1, 1, 1, 1], 7, 0], [[3, 10]]), ('regression: logical to visual mapping', [[2, 2, 2, 2, 1, 1, 1], 0, 1], [[3, 4]]), ('backward selection', [[1, 1, 1], 3, 1], [[0, 2]]), ('selection crossing direction change', [[0, 0, 1, 1, 0], 1, 4], [[1, 4]]), ('control layout', [[2, 3, 3, 3, 3, 3, 0, 0, 0, 2, 2], 6, 9], [[6, 9]]), ('control layout', [[2, 3, 3], 3, 3], [])], [('regression: logical to visual mapping', [[3, 3, 3, 3, 1], 4, 5], [[0, 1]]), ('regression: logical to visual mapping', [[1, 1, 1, 2], 3, 0], [[1, 4]]), ('regression: logical to visual mapping', [[1, 1, 1, 3, 2, 2, 2, 2, 4, 4], 2, 6], [[0, 3], [7, 8]]), ('regression: logical to visual mapping', [[2, 2, 2, 2, 2, 2, 1, 1, 1], 2, 1], [[4, 5]]), ('selection crossing direction change', [[0, 0, 1, 1, 0], 1, 4], [[1, 4]]), ('backward selection', [[1, 1, 1], 3, 1], [[0, 2]]), ('control layout', [[2, 2], 2, 1], [[1, 2]]), ('control layout', [[0, 0, 0, 0, 0, 1, 1, 1], 4, 2], [[2, 4]])], [('regression: logical to visual mapping', [[3, 3], 1, 0], [[1, 2]]), ('regression: logical to visual mapping', [[2, 2, 2, 1, 4, 4], 4, 3], [[2, 3]]), ('regression: logical to visual mapping', [[1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 1], 6, 3], [[5, 8]]), ('regression: logical to visual mapping', [[1, 4, 4, 4, 4, 4, 4, 1, 1, 2], 10, 5], [[0, 3], [7, 9]]), ('selection crossing direction change', [[0, 0, 1, 1, 0], 1, 4], [[1, 4]]), ('backward selection', [[1, 1, 1], 3, 1], [[0, 2]]), ('control layout', [[1, 0, 0, 1, 1], 2, 0], [[0, 2]]), ('control layout', [[2, 1, 1, 1, 1, 1, 4], 7, 0], [[0, 7]])], [('regression: logical to visual mapping', [[2, 2, 2, 2, 2, 2, 1, 1], 0, 3], [[2, 5]]), ('regression: logical to visual mapping', [[2, 4, 1, 1, 1, 1, 1], 6, 1], [[1, 5], [6, 7]]), ('regression: logical to visual mapping', [[4, 4, 4, 4, 4, 4, 1, 1, 1, 2, 2], 9, 1], [[2, 5], [6, 11]]), ('regression: logical to visual mapping', [[2, 1, 1, 1, 1, 1, 1, 1, 2, 4, 4], 7, 10], [[0, 2], [3, 4]]), ('backward selection', [[1, 1, 1], 3, 1], [[0, 2]]), ('selection crossing direction change', [[0, 0, 1, 1, 0], 1, 4], [[1, 4]]), ('control layout', [[2, 2, 2, 2, 2, 4], 2, 0], [[0, 2]]), ('control layout', [[1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1], 10, 10], [])]]
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 fixtureActualExpectedOutcome
backward selection[[0, 2]][[0, 2]]Passed
regression: logical to visual mapping[[1, 3]][[3, 5]]Failed
regression: logical to visual mapping[[5, 6], [8, 10]][[5, 8]]Failed
regression: logical to visual mapping[[1, 2]][[3, 4]]Failed
selection crossing direction change[[1, 4]][[1, 4]]Passed
control layout[][]Passed
control layout[[2, 4]][[2, 4]]Passed
control layout[[2, 8]][[2, 8]]Passed

SHA-256 / 7f2fa38ed1b0b88326cd113e8dde91832f76f72325dfce2b30d1a89ddb393fb5

3 / The verified repair

Exit 0
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(x):
    def reorder(lv):
        vis = list(range(len(lv)))
        odd = [l for l in lv if l % 2 == 1]
        if not odd:
            return vis
        for lev in range(max(lv), min(odd) - 1, -1):
            i = 0
            while i < len(vis):
                if lv[vis[i]] >= lev:
                    j = i
                    while j < len(vis) and lv[vis[j]] >= lev:
                        j += 1
                    vis[i:j] = vis[i:j][::-1]
                    i = j
                else:
                    i += 1
        return vis
    
    levels, a, b = x
    a, b = min(a, b), max(a, b)
    vis = reorder(levels)
    pos = [0] * len(levels)
    for v, i in enumerate(vis):
        pos[i] = v
    sel = sorted(pos[i] for i in range(a, b))
    rects = []
    for p in sel:
        if rects and rects[-1][1] == p:
            rects[-1][1] = p + 1
        else:
            rects.append([p, p + 1])
    return rects
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('backward selection', [[1, 1, 1], 3, 1], [[0, 2]]), ('regression: logical to visual mapping', [[4, 4, 2, 4, 1], 4, 2], [[3, 5]]), ('regression: logical to visual mapping', [[1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 1], 6, 3], [[5, 8]]), ('regression: logical to visual mapping', [[4, 4, 4, 1], 2, 3], [[3, 4]]), ('selection crossing direction change', [[0, 0, 1, 1, 0], 1, 4], [[1, 4]]), ('control layout', [[3, 3, 3, 3, 3, 3, 3, 3, 0, 3, 3], 10, 10], []), ('control layout', [[3, 2, 2, 2, 2, 2], 2, 4], [[2, 4]]), ('control layout', [[2, 2, 3, 3, 2, 2, 0, 0], 8, 2], [[2, 8]])], [('regression: logical to visual mapping', [[2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 0], 12, 9], [[0, 2], [11, 12]]), ('regression: logical to visual mapping', [[1, 0, 1, 2, 2, 2, 3, 2, 1, 1, 3], 9, 4], [[4, 5], [6, 10]]), ('regression: logical to visual mapping', [[4, 4, 2, 2, 1, 1, 1, 1, 1, 1], 7, 0], [[3, 10]]), ('regression: logical to visual mapping', [[2, 2, 2, 2, 1, 1, 1], 0, 1], [[3, 4]]), ('backward selection', [[1, 1, 1], 3, 1], [[0, 2]]), ('selection crossing direction change', [[0, 0, 1, 1, 0], 1, 4], [[1, 4]]), ('control layout', [[2, 3, 3, 3, 3, 3, 0, 0, 0, 2, 2], 6, 9], [[6, 9]]), ('control layout', [[2, 3, 3], 3, 3], [])], [('regression: logical to visual mapping', [[3, 3, 3, 3, 1], 4, 5], [[0, 1]]), ('regression: logical to visual mapping', [[1, 1, 1, 2], 3, 0], [[1, 4]]), ('regression: logical to visual mapping', [[1, 1, 1, 3, 2, 2, 2, 2, 4, 4], 2, 6], [[0, 3], [7, 8]]), ('regression: logical to visual mapping', [[2, 2, 2, 2, 2, 2, 1, 1, 1], 2, 1], [[4, 5]]), ('selection crossing direction change', [[0, 0, 1, 1, 0], 1, 4], [[1, 4]]), ('backward selection', [[1, 1, 1], 3, 1], [[0, 2]]), ('control layout', [[2, 2], 2, 1], [[1, 2]]), ('control layout', [[0, 0, 0, 0, 0, 1, 1, 1], 4, 2], [[2, 4]])], [('regression: logical to visual mapping', [[3, 3], 1, 0], [[1, 2]]), ('regression: logical to visual mapping', [[2, 2, 2, 1, 4, 4], 4, 3], [[2, 3]]), ('regression: logical to visual mapping', [[1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 1], 6, 3], [[5, 8]]), ('regression: logical to visual mapping', [[1, 4, 4, 4, 4, 4, 4, 1, 1, 2], 10, 5], [[0, 3], [7, 9]]), ('selection crossing direction change', [[0, 0, 1, 1, 0], 1, 4], [[1, 4]]), ('backward selection', [[1, 1, 1], 3, 1], [[0, 2]]), ('control layout', [[1, 0, 0, 1, 1], 2, 0], [[0, 2]]), ('control layout', [[2, 1, 1, 1, 1, 1, 4], 7, 0], [[0, 7]])], [('regression: logical to visual mapping', [[2, 2, 2, 2, 2, 2, 1, 1], 0, 3], [[2, 5]]), ('regression: logical to visual mapping', [[2, 4, 1, 1, 1, 1, 1], 6, 1], [[1, 5], [6, 7]]), ('regression: logical to visual mapping', [[4, 4, 4, 4, 4, 4, 1, 1, 1, 2, 2], 9, 1], [[2, 5], [6, 11]]), ('regression: logical to visual mapping', [[2, 1, 1, 1, 1, 1, 1, 1, 2, 4, 4], 7, 10], [[0, 2], [3, 4]]), ('backward selection', [[1, 1, 1], 3, 1], [[0, 2]]), ('selection crossing direction change', [[0, 0, 1, 1, 0], 1, 4], [[1, 4]]), ('control layout', [[2, 2, 2, 2, 2, 4], 2, 0], [[0, 2]]), ('control layout', [[1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1], 10, 10], [])]]
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 fixtureActualExpectedOutcome
backward selection[[0, 2]][[0, 2]]Passed
regression: logical to visual mapping[[3, 5]][[3, 5]]Passed
regression: logical to visual mapping[[5, 8]][[5, 8]]Passed
regression: logical to visual mapping[[3, 4]][[3, 4]]Passed
selection crossing direction change[[1, 4]][[1, 4]]Passed
control layout[][]Passed
control layout[[2, 4]][[2, 4]]Passed
control layout[[2, 8]][[2, 8]]Passed

SHA-256 / 894a1fbe187dcd3458054d70abb5e3fa86703e4e930450478e36089c832a0c8a

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:56.122203+00:00.

Case digest / df1afd9e63324bb5cce3de0a3e6a1c12b857d64adf2f193f558c102dcf7da674