FAILURE MAP
← Case archive

FA-80296 / Typography line breaking / Open access

Balanced headline wrapping: interword space in counting · case 01

Balanced widths are too narrow and lines overflow when laid out.

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

ROOT CAUSE

The line counter ignores the space between words.

VERIFIED REPAIR

Count one space between words when simulating the wrap.

Unsuccessful approach: A strict comparison miscounts exact fits.

Case contract

Input [words, width]. Let L be the greedy line count at width (["overflow"] if a word is wider). Find the smallest width w (>= longest word) whose greedy wrap needs no more than L lines, then return the greedy wrap at w.

Why this case matters

Line breaking decides where paragraphs wrap on screen and in print; a wrong decision point shifts every following line.

1 / The failure

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

N = 1
observations = []
def solve(x):
    words, width = x
    def lines_for(w):
        count, cur = 0, -1
        for t in words:
            if len(t) > w:
                return None
            if cur == -1:
                cur = len(t)
                count = 1
            elif cur + len(t) <= w:
                cur += 1 + len(t)
            else:
                count += 1
                cur = len(t)
        return count
    target = lines_for(width)
    if target is None:
        return ['overflow']
    lo = max(len(t) for t in words)
    hi = width
    while lo < hi:
        mid = (lo + hi) // 2
        c = lines_for(mid)
        if c is not None and c <= target:
            hi = mid
        else:
            lo = mid + 1
    out, cur = [], ''
    for t in words:
        cand = t if not cur else cur + ' ' + t
        if len(cand) <= lo:
            cur = cand
        else:
            out.append(cur)
            cur = t
    out.append(cur)
    return out
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('two balanced lines', [['the', 'type', 'grid', 'is', 'on', 'serif'], 22], ['the type grid', 'is on serif']), ('regression: interword space in counting', [['at', 'kerning', 'baseline', 'kerning', 'x', 'a', 'at', 'x'], 29], ['at kerning baseline', 'kerning x a at x']), ('regression: interword space in counting', [['is', 'on', 'the', 'grid', 'a', 'is', 'measure'], 14], ['is on the grid', 'a is measure']), ('regression: interword space in counting', [['at', 'serif', 'kerning', 'on', 'the', 'serif', 'at', 'the', 'type'], 12], ['at serif', 'kerning on', 'the serif', 'at the type']), ('word exactly the width', [['baseline', 'x'], 8], ['baseline', 'x']), ('control layout', [['measure', 'x', 'serif', 'a', 'a', 'x', 'is', 'of', 'x'], 6], ['overflow']), ('control layout', [['grid', 'is', 'kerning', 'grid'], 10], ['grid is', 'kerning', 'grid']), ('control layout', [['grid', 'a', 'at', 'serif', 'serif'], 5], ['grid', 'a at', 'serif', 'serif'])], [('regression: interword space in counting', [['x', 'a'], 25], ['x a']), ('regression: interword space in counting', [['of', 'kerning', 'is'], 18], ['of kerning is']), ('regression: interword space in counting', [['on', 'serif', 'measure', 'the', 'on', 'the'], 16], ['on serif measure', 'the on the']), ('regression: interword space in counting', [['of', 'x', 'at', 'grid', 'measure', 'at', 'the', 'at', 'the'], 10], ['of x at', 'grid', 'measure at', 'the at the']), ('two balanced lines', [['the', 'type', 'grid', 'is', 'on', 'serif'], 22], ['the type grid', 'is on serif']), ('word exactly the width', [['baseline', 'x'], 8], ['baseline', 'x']), ('control layout', [['measure', 'kerning', 'a'], 7], ['measure', 'kerning', 'a']), ('control layout', [['is', 'is', 'the', 'serif'], 5], ['is is', 'the', 'serif'])], [('regression: interword space in counting', [['ink', 'a', 'a'], 6], ['ink', 'a a']), ('regression: interword space in counting', [['kerning', 'baseline', 'a', 'serif'], 27], ['kerning baseline a serif']), ('regression: interword space in counting', [['baseline', 'is'], 11], ['baseline is']), ('regression: interword space in counting', [['of', 'a', 'kerning', 'of', 'kerning', 'of', 'type', 'the', 'x'], 21], ['of a kerning of', 'kerning of type the x']), ('two balanced lines', [['the', 'type', 'grid', 'is', 'on', 'serif'], 22], ['the type grid', 'is on serif']), ('word exactly the width', [['baseline', 'x'], 8], ['baseline', 'x']), ('control layout', [['a', 'serif', 'serif', 'baseline', 'grid', 'measure'], 11], ['a serif', 'serif', 'baseline', 'grid', 'measure']), ('control layout', [['x', 'baseline', 'a', 'measure', 'is'], 5], ['overflow'])], [('regression: interword space in counting', [['at', 'kerning', 'at', 'measure'], 29], ['at kerning at measure']), ('regression: interword space in counting', [['of', 'is', 'the', 'on', 'kerning'], 17], ['of is the', 'on kerning']), ('regression: interword space in counting', [['the', 'x', 'type', 'serif', 'grid', 'is', 'a'], 17], ['the x type', 'serif grid is a']), ('regression: interword space in counting', [['baseline', 'measure', 'measure'], 15], ['baseline', 'measure measure']), ('two balanced lines', [['the', 'type', 'grid', 'is', 'on', 'serif'], 22], ['the type grid', 'is on serif']), ('word exactly the width', [['baseline', 'x'], 8], ['baseline', 'x']), ('control layout', [['kerning', 'on', 'the'], 9], ['kerning', 'on the']), ('control layout', [['x', 'baseline', 'is', 'ink', 'type', 'measure', 'on', 'a', 'the'], 8], ['x', 'baseline', 'is ink', 'type', 'measure', 'on a the'])], [('regression: interword space in counting', [['grid', 'on', 'baseline', 'x', 'x', 'grid', 'x', 'a', 'is'], 30], ['grid on baseline', 'x x grid x a is']), ('regression: interword space in counting', [['is', 'grid', 'type', 'ink', 'x', 'grid', 'grid'], 16], ['is grid type', 'ink x grid grid']), ('regression: interword space in counting', [['the', 'at', 'of', 'on', 'on', 'serif'], 17], ['the at of', 'on on serif']), ('regression: interword space in counting', [['kerning', 'kerning', 'ink', 'ink', 'type', 'baseline'], 15], ['kerning kerning', 'ink ink type', 'baseline']), ('word exactly the width', [['baseline', 'x'], 8], ['baseline', 'x']), ('two balanced lines', [['the', 'type', 'grid', 'is', 'on', 'serif'], 22], ['the type grid', 'is on serif']), ('control layout', [['grid', 'serif', 'type'], 6], ['grid', 'serif', 'type']), ('control layout', [['kerning', 'measure', 'type', 'on', 'measure', 'x', 'baseline'], 6], ['overflow'])]]
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
two balanced lines['the type', 'grid is on', 'serif']['the type grid', 'is on serif']Failed
regression: interword space in counting['at kerning', 'baseline kerning x', 'a at x']['at kerning baseline', 'kerning x a at x']Failed
regression: interword space in counting['is on the', 'grid a is', 'measure']['is on the grid', 'a is measure']Failed
regression: interword space in counting['at serif', 'kerning on', 'the serif', 'at the', 'type']['at serif', 'kerning on', 'the serif', 'at the type']Failed
word exactly the width['baseline', 'x']['baseline', 'x']Passed
control layout['overflow']['overflow']Passed
control layout['grid is', 'kerning', 'grid']['grid is', 'kerning', 'grid']Passed
control layout['grid', 'a at', 'serif', 'serif']['grid', 'a at', 'serif', 'serif']Passed

SHA-256 / 6cca1966f0b11eb1d4b75abad88575dff4c868b54ef81daee672711b3a3ff107

2 / The unsuccessful fix

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

N = 1
observations = []
def solve(x):
    words, width = x
    def lines_for(w):
        count, cur = 0, -1
        for t in words:
            if len(t) > w:
                return None
            if cur == -1:
                cur = len(t)
                count = 1
            elif cur + 1 + len(t) < w:
                cur += 1 + len(t)
            else:
                count += 1
                cur = len(t)
        return count
    target = lines_for(width)
    if target is None:
        return ['overflow']
    lo = max(len(t) for t in words)
    hi = width
    while lo < hi:
        mid = (lo + hi) // 2
        c = lines_for(mid)
        if c is not None and c <= target:
            hi = mid
        else:
            lo = mid + 1
    out, cur = [], ''
    for t in words:
        cand = t if not cur else cur + ' ' + t
        if len(cand) <= lo:
            cur = cand
        else:
            out.append(cur)
            cur = t
    out.append(cur)
    return out
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('two balanced lines', [['the', 'type', 'grid', 'is', 'on', 'serif'], 22], ['the type grid', 'is on serif']), ('regression: interword space in counting', [['at', 'kerning', 'baseline', 'kerning', 'x', 'a', 'at', 'x'], 29], ['at kerning baseline', 'kerning x a at x']), ('regression: interword space in counting', [['is', 'on', 'the', 'grid', 'a', 'is', 'measure'], 14], ['is on the grid', 'a is measure']), ('regression: interword space in counting', [['at', 'serif', 'kerning', 'on', 'the', 'serif', 'at', 'the', 'type'], 12], ['at serif', 'kerning on', 'the serif', 'at the type']), ('word exactly the width', [['baseline', 'x'], 8], ['baseline', 'x']), ('control layout', [['measure', 'x', 'serif', 'a', 'a', 'x', 'is', 'of', 'x'], 6], ['overflow']), ('control layout', [['grid', 'is', 'kerning', 'grid'], 10], ['grid is', 'kerning', 'grid']), ('control layout', [['grid', 'a', 'at', 'serif', 'serif'], 5], ['grid', 'a at', 'serif', 'serif'])], [('regression: interword space in counting', [['x', 'a'], 25], ['x a']), ('regression: interword space in counting', [['of', 'kerning', 'is'], 18], ['of kerning is']), ('regression: interword space in counting', [['on', 'serif', 'measure', 'the', 'on', 'the'], 16], ['on serif measure', 'the on the']), ('regression: interword space in counting', [['of', 'x', 'at', 'grid', 'measure', 'at', 'the', 'at', 'the'], 10], ['of x at', 'grid', 'measure at', 'the at the']), ('two balanced lines', [['the', 'type', 'grid', 'is', 'on', 'serif'], 22], ['the type grid', 'is on serif']), ('word exactly the width', [['baseline', 'x'], 8], ['baseline', 'x']), ('control layout', [['measure', 'kerning', 'a'], 7], ['measure', 'kerning', 'a']), ('control layout', [['is', 'is', 'the', 'serif'], 5], ['is is', 'the', 'serif'])], [('regression: interword space in counting', [['ink', 'a', 'a'], 6], ['ink', 'a a']), ('regression: interword space in counting', [['kerning', 'baseline', 'a', 'serif'], 27], ['kerning baseline a serif']), ('regression: interword space in counting', [['baseline', 'is'], 11], ['baseline is']), ('regression: interword space in counting', [['of', 'a', 'kerning', 'of', 'kerning', 'of', 'type', 'the', 'x'], 21], ['of a kerning of', 'kerning of type the x']), ('two balanced lines', [['the', 'type', 'grid', 'is', 'on', 'serif'], 22], ['the type grid', 'is on serif']), ('word exactly the width', [['baseline', 'x'], 8], ['baseline', 'x']), ('control layout', [['a', 'serif', 'serif', 'baseline', 'grid', 'measure'], 11], ['a serif', 'serif', 'baseline', 'grid', 'measure']), ('control layout', [['x', 'baseline', 'a', 'measure', 'is'], 5], ['overflow'])], [('regression: interword space in counting', [['at', 'kerning', 'at', 'measure'], 29], ['at kerning at measure']), ('regression: interword space in counting', [['of', 'is', 'the', 'on', 'kerning'], 17], ['of is the', 'on kerning']), ('regression: interword space in counting', [['the', 'x', 'type', 'serif', 'grid', 'is', 'a'], 17], ['the x type', 'serif grid is a']), ('regression: interword space in counting', [['baseline', 'measure', 'measure'], 15], ['baseline', 'measure measure']), ('two balanced lines', [['the', 'type', 'grid', 'is', 'on', 'serif'], 22], ['the type grid', 'is on serif']), ('word exactly the width', [['baseline', 'x'], 8], ['baseline', 'x']), ('control layout', [['kerning', 'on', 'the'], 9], ['kerning', 'on the']), ('control layout', [['x', 'baseline', 'is', 'ink', 'type', 'measure', 'on', 'a', 'the'], 8], ['x', 'baseline', 'is ink', 'type', 'measure', 'on a the'])], [('regression: interword space in counting', [['grid', 'on', 'baseline', 'x', 'x', 'grid', 'x', 'a', 'is'], 30], ['grid on baseline', 'x x grid x a is']), ('regression: interword space in counting', [['is', 'grid', 'type', 'ink', 'x', 'grid', 'grid'], 16], ['is grid type', 'ink x grid grid']), ('regression: interword space in counting', [['the', 'at', 'of', 'on', 'on', 'serif'], 17], ['the at of', 'on on serif']), ('regression: interword space in counting', [['kerning', 'kerning', 'ink', 'ink', 'type', 'baseline'], 15], ['kerning kerning', 'ink ink type', 'baseline']), ('word exactly the width', [['baseline', 'x'], 8], ['baseline', 'x']), ('two balanced lines', [['the', 'type', 'grid', 'is', 'on', 'serif'], 22], ['the type grid', 'is on serif']), ('control layout', [['grid', 'serif', 'type'], 6], ['grid', 'serif', 'type']), ('control layout', [['kerning', 'measure', 'type', 'on', 'measure', 'x', 'baseline'], 6], ['overflow'])]]
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
two balanced lines['the type grid', 'is on serif']['the type grid', 'is on serif']Passed
regression: interword space in counting['at kerning baseline', 'kerning x a at x']['at kerning baseline', 'kerning x a at x']Passed
regression: interword space in counting['is on the', 'grid a is', 'measure']['is on the grid', 'a is measure']Failed
regression: interword space in counting['at serif', 'kerning on', 'the serif at', 'the type']['at serif', 'kerning on', 'the serif', 'at the type']Failed
word exactly the width['baseline', 'x']['baseline', 'x']Passed
control layout['overflow']['overflow']Passed
control layout['grid is', 'kerning', 'grid']['grid is', 'kerning', 'grid']Passed
control layout['grid', 'a at', 'serif', 'serif']['grid', 'a at', 'serif', 'serif']Passed

SHA-256 / 643e9423e58e3558695caa4d7c47bd9f93d726b8be19f8453144f8e4e80026a8

3 / The verified repair

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

N = 1
observations = []
def solve(x):
    words, width = x
    def lines_for(w):
        count, cur = 0, -1
        for t in words:
            if len(t) > w:
                return None
            if cur == -1:
                cur = len(t)
                count = 1
            elif cur + 1 + len(t) <= w:
                cur += 1 + len(t)
            else:
                count += 1
                cur = len(t)
        return count
    target = lines_for(width)
    if target is None:
        return ['overflow']
    lo = max(len(t) for t in words)
    hi = width
    while lo < hi:
        mid = (lo + hi) // 2
        c = lines_for(mid)
        if c is not None and c <= target:
            hi = mid
        else:
            lo = mid + 1
    out, cur = [], ''
    for t in words:
        cand = t if not cur else cur + ' ' + t
        if len(cand) <= lo:
            cur = cand
        else:
            out.append(cur)
            cur = t
    out.append(cur)
    return out
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('two balanced lines', [['the', 'type', 'grid', 'is', 'on', 'serif'], 22], ['the type grid', 'is on serif']), ('regression: interword space in counting', [['at', 'kerning', 'baseline', 'kerning', 'x', 'a', 'at', 'x'], 29], ['at kerning baseline', 'kerning x a at x']), ('regression: interword space in counting', [['is', 'on', 'the', 'grid', 'a', 'is', 'measure'], 14], ['is on the grid', 'a is measure']), ('regression: interword space in counting', [['at', 'serif', 'kerning', 'on', 'the', 'serif', 'at', 'the', 'type'], 12], ['at serif', 'kerning on', 'the serif', 'at the type']), ('word exactly the width', [['baseline', 'x'], 8], ['baseline', 'x']), ('control layout', [['measure', 'x', 'serif', 'a', 'a', 'x', 'is', 'of', 'x'], 6], ['overflow']), ('control layout', [['grid', 'is', 'kerning', 'grid'], 10], ['grid is', 'kerning', 'grid']), ('control layout', [['grid', 'a', 'at', 'serif', 'serif'], 5], ['grid', 'a at', 'serif', 'serif'])], [('regression: interword space in counting', [['x', 'a'], 25], ['x a']), ('regression: interword space in counting', [['of', 'kerning', 'is'], 18], ['of kerning is']), ('regression: interword space in counting', [['on', 'serif', 'measure', 'the', 'on', 'the'], 16], ['on serif measure', 'the on the']), ('regression: interword space in counting', [['of', 'x', 'at', 'grid', 'measure', 'at', 'the', 'at', 'the'], 10], ['of x at', 'grid', 'measure at', 'the at the']), ('two balanced lines', [['the', 'type', 'grid', 'is', 'on', 'serif'], 22], ['the type grid', 'is on serif']), ('word exactly the width', [['baseline', 'x'], 8], ['baseline', 'x']), ('control layout', [['measure', 'kerning', 'a'], 7], ['measure', 'kerning', 'a']), ('control layout', [['is', 'is', 'the', 'serif'], 5], ['is is', 'the', 'serif'])], [('regression: interword space in counting', [['ink', 'a', 'a'], 6], ['ink', 'a a']), ('regression: interword space in counting', [['kerning', 'baseline', 'a', 'serif'], 27], ['kerning baseline a serif']), ('regression: interword space in counting', [['baseline', 'is'], 11], ['baseline is']), ('regression: interword space in counting', [['of', 'a', 'kerning', 'of', 'kerning', 'of', 'type', 'the', 'x'], 21], ['of a kerning of', 'kerning of type the x']), ('two balanced lines', [['the', 'type', 'grid', 'is', 'on', 'serif'], 22], ['the type grid', 'is on serif']), ('word exactly the width', [['baseline', 'x'], 8], ['baseline', 'x']), ('control layout', [['a', 'serif', 'serif', 'baseline', 'grid', 'measure'], 11], ['a serif', 'serif', 'baseline', 'grid', 'measure']), ('control layout', [['x', 'baseline', 'a', 'measure', 'is'], 5], ['overflow'])], [('regression: interword space in counting', [['at', 'kerning', 'at', 'measure'], 29], ['at kerning at measure']), ('regression: interword space in counting', [['of', 'is', 'the', 'on', 'kerning'], 17], ['of is the', 'on kerning']), ('regression: interword space in counting', [['the', 'x', 'type', 'serif', 'grid', 'is', 'a'], 17], ['the x type', 'serif grid is a']), ('regression: interword space in counting', [['baseline', 'measure', 'measure'], 15], ['baseline', 'measure measure']), ('two balanced lines', [['the', 'type', 'grid', 'is', 'on', 'serif'], 22], ['the type grid', 'is on serif']), ('word exactly the width', [['baseline', 'x'], 8], ['baseline', 'x']), ('control layout', [['kerning', 'on', 'the'], 9], ['kerning', 'on the']), ('control layout', [['x', 'baseline', 'is', 'ink', 'type', 'measure', 'on', 'a', 'the'], 8], ['x', 'baseline', 'is ink', 'type', 'measure', 'on a the'])], [('regression: interword space in counting', [['grid', 'on', 'baseline', 'x', 'x', 'grid', 'x', 'a', 'is'], 30], ['grid on baseline', 'x x grid x a is']), ('regression: interword space in counting', [['is', 'grid', 'type', 'ink', 'x', 'grid', 'grid'], 16], ['is grid type', 'ink x grid grid']), ('regression: interword space in counting', [['the', 'at', 'of', 'on', 'on', 'serif'], 17], ['the at of', 'on on serif']), ('regression: interword space in counting', [['kerning', 'kerning', 'ink', 'ink', 'type', 'baseline'], 15], ['kerning kerning', 'ink ink type', 'baseline']), ('word exactly the width', [['baseline', 'x'], 8], ['baseline', 'x']), ('two balanced lines', [['the', 'type', 'grid', 'is', 'on', 'serif'], 22], ['the type grid', 'is on serif']), ('control layout', [['grid', 'serif', 'type'], 6], ['grid', 'serif', 'type']), ('control layout', [['kerning', 'measure', 'type', 'on', 'measure', 'x', 'baseline'], 6], ['overflow'])]]
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
two balanced lines['the type grid', 'is on serif']['the type grid', 'is on serif']Passed
regression: interword space in counting['at kerning baseline', 'kerning x a at x']['at kerning baseline', 'kerning x a at x']Passed
regression: interword space in counting['is on the grid', 'a is measure']['is on the grid', 'a is measure']Passed
regression: interword space in counting['at serif', 'kerning on', 'the serif', 'at the type']['at serif', 'kerning on', 'the serif', 'at the type']Passed
word exactly the width['baseline', 'x']['baseline', 'x']Passed
control layout['overflow']['overflow']Passed
control layout['grid is', 'kerning', 'grid']['grid is', 'kerning', 'grid']Passed
control layout['grid', 'a at', 'serif', 'serif']['grid', 'a at', 'serif', 'serif']Passed

SHA-256 / 6d0b49dfd2fa076ad5812ab907dd18b5a9e749f218abe4ad01f72f239655a6b8

Verification & scope

A deterministic toy typesetting model with integer widths and a stipulated rule set; it does not claim conformance to any engine. 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:52.509609+00:00.

Case digest / 13cb0f38b619c4ef2892456e170f02c4c9b533794cd2bc66f5f72c196f0f16a5