FA-80026 / Typography line breaking / Open access
CJK kinsoku line breaking: minimum line content · case 01
Short measures leave two-character lines where one would be legal.
ROOT CAUSE
The push-out guard keeps two characters on the line instead of one.
VERIFIED REPAIR
Allow pushing back until a single character remains on the line.
Unsuccessful approach: Keeping half the measure refuses legitimate push-outs.
Case contract
Input [text of full-width characters, line length L]. Lines take L characters. If the next character is a hanging comma/period (、。,.) and is not itself followed by a line-start-prohibited character, it hangs on the line (burasage). Otherwise move characters to the next line while the next line would start with a prohibited character (、。,.)」』!?ー and small kana), then while the line would end with an opening bracket; a line keeps at least one character. Return the lines.
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):
text, L = x
NO_START = '、。,.)」』!?ーぁぃぅぇぉっゃゅょ'
NO_END = '(「『'
HANG = '、。,.'
lines = []
pos = 0
n = len(text)
while pos < n:
end = pos + L
if end >= n:
lines.append(text[pos:])
break
if text[end] in HANG and (end + 1 >= n or text[end + 1] not in NO_START):
end += 1
else:
while end > pos + 2 and text[end] in NO_START:
end -= 1
while end > pos + 1 and text[end - 1] in NO_END:
end -= 1
lines.append(text[pos:end])
pos = end
return lines
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('regression: minimum line content', ['『ー』かい組ー(本」ー、、本か語っけーえ組か', 3], ['『ー』', 'かい', '組ー', '(', '本', '」ー、、', '本か', '語っ', 'けーえ', '組か']), ('regression: minimum line content', ['ゃ、』ーっお字き『あーけお(こ文けゃ』本語組ゃ文', 4], ['ゃ', '、』ーっ', 'お字き', '『あーけ', 'お(こ文', 'けゃ』本', '語組ゃ文']), ('regression: minimum line content', ['う版あう。、っ』、)「字。あかか、『。いおきゃ', 4], ['う版あ', 'う', '。', '、', 'っ』、)', '「字。あ', 'かか、『。', 'いおきゃ']), ('partial-repair probe', ['、ーく」ゃ』』ー本え組きけ本日こ』', 7], ['、ー', 'く」ゃ』』ー本', 'え組きけ本日', 'こ』']), ('small kana prohibited at line start', ['日本語かっこいい', 4], ['日本語', 'かっこい', 'い']), ('period followed by bracket cannot hang', ['日本語文。」字組', 4], ['日本語', '文。」字', '組']), ('control layout', [')っ(こき文う字)お字本かー語本(字か', 4], [')っ(こ', 'き文う', '字)お字', '本かー語', '本(字か']), ('control layout', ['こえきかう「((版', 7], ['こえきかう', '「((版'])], [('regression: minimum line content', ['文け『い、あ。「日っ」『', 3], ['文け', '『い、', 'あ。', '「', '日っ」', '『']), ('regression: minimum line content', ['け(こーっ版く」)あ)う組)けあ(う', 3], ['け', '(', 'こーっ', '版', 'く」)', 'あ)う', '組)け', 'あ(う']), ('regression: minimum line content', ['「)。文お。い組、、い)、、っ」け「あえいけ日、', 4], ['「)。文', 'お。い', '組、、', 'い', ')', '、、っ」', 'け「あえ', 'いけ日、']), ('regression: minimum line content', ['けけーうけゃ)(っ』』)ゃっ組)お', 4], ['けけーう', 'けゃ)', '(', 'っ', '』', '』)ゃっ', '組)お']), ('closing bracket pushes out', ['日本語文」字組版', 4], ['日本語', '文」字組', '版']), ('period hangs past the measure', ['日本語文。字組版', 4], ['日本語文。', '字組版']), ('control layout', ['()字「文版い字ー「版ーっ「。』組字組けあか「', 8], ['()字「文版い', '字ー「版ーっ', '「。』組字組けあ', 'か「']), ('control layout', ['『ー組い、文おけええ「本文か語、ゃお版(か語版『', 6], ['『ー組い、文', 'おけええ「本', '文か語、ゃお', '版(か語版『'])], [('regression: minimum line content', ['、あゃく文え、『か、)版」日ゃ(文『か', 3], ['、あゃ', 'く文え、', '『', 'か、)', '版」', '日ゃ', '(文', '『か']), ('regression: minimum line content', ['文え(』い。版組(あえう語』、)ー本。『組', 3], ['文え', '(』い。', '版組', '(あえ', 'う', '語', '』', '、)ー', '本。', '『組']), ('regression: minimum line content', ['字きあ)ー『、いあけーけ字字、(き。ー』」」』(', 5], ['字きあ)ー', '『、いあ', 'けーけ字字、', '(', 'き', '。', 'ー』」」』', '(']), ('regression: minimum line content', ['版(組)ーー。)日くああ本', 5], ['版', '(', '組', ')ーー。)', '日くああ本']), ('period followed by bracket cannot hang', ['日本語文。」字組', 4], ['日本語', '文。」字', '組']), ('small kana prohibited at line start', ['日本語かっこいい', 4], ['日本語', 'かっこい', 'い']), ('control layout', ['え、かけ語か「『いい日う字え', 6], ['え、かけ語か', '「『いい日う', '字え']), ('control layout', ['けいかお本。。き、こお」こ語語「か組っ「本「', 5], ['けいかお', '本。。き、', 'こお」こ語', '語「か組っ', '「本「'])], [('regression: minimum line content', ['け(こーっ版く」)あ)う組)けあ(う', 3], ['け', '(', 'こーっ', '版', 'く」)', 'あ)う', '組)け', 'あ(う']), ('regression: minimum line content', ['けこけ」組』かお字本いく』「本(い(ゃゃ)かゃ字', 3], ['けこ', 'け」', '組』か', 'お字本', 'いく』', '「本', '(い', '(', 'ゃゃ)', 'かゃ字']), ('regression: minimum line content', ['あく』』ゃあ版き「文』日ううあこ', 4], ['あ', 'く』』ゃ', 'あ版き', '「文』日', 'ううあこ']), ('regression: minimum line content', ['う版あう。、っ』、)「字。あかか、『。いおきゃ', 4], ['う版あ', 'う', '。', '、', 'っ』、)', '「字。あ', 'かか、『。', 'いおきゃ']), ('opening bracket at line end', ['日本語「文字」組版', 4], ['日本語', '「文字」', '組版']), ('period hangs past the measure', ['日本語文。字組版', 4], ['日本語文。', '字組版']), ('control layout', ['本。け本きえこ』', 5], ['本。け本き', 'えこ』']), ('control layout', ['ゃ語く)う、『こ日お組』き『日くこおおい」文ゃ『', 5], ['ゃ語く)う、', '『こ日お', '組』き『日', 'くこおお', 'い」文ゃ『'])], [('regression: minimum line content', ['文ゃー語あ。かこ本か、字、字「ゃおゃ』」、っ', 4], ['文ゃー語', 'あ。かこ', '本か、字、', '字「ゃ', 'お', 'ゃ', '』」、っ']), ('regression: minimum line content', ['字きあ)ー『、いあけーけ字字、(き。ー』」」』(', 5], ['字きあ)ー', '『、いあ', 'けーけ字字、', '(', 'き', '。', 'ー』」」』', '(']), ('regression: minimum line content', ['けけーうけゃ)(っ』』)ゃっ組)お', 4], ['けけーう', 'けゃ)', '(', 'っ', '』', '』)ゃっ', '組)お']), ('regression: minimum line content', ['語字、え『えくゃえー』』ーこ組「日『。(', 4], ['語字、え', '『えくゃ', 'え', 'ー』』ー', 'こ組「日', '『。(']), ('period hangs past the measure', ['日本語文。字組版', 4], ['日本語文。', '字組版']), ('period followed by bracket cannot hang', ['日本語文。」字組', 4], ['日本語', '文。」字', '組']), ('control layout', ['語け本日ゃ」)「字、字字', 5], ['語け本', '日ゃ」)', '「字、字字']), ('control layout', ['「『日、く)、」組)っうお。(', 6], ['「『日、', 'く)、」', '組)っうお。', '('])]]
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: minimum line content | ['『ー』', 'かい', '組ー', '(本', '」ー、、', '本か', '語っ', 'けーえ', '組か'] | ['『ー』', 'かい', '組ー', '(', '本', '」ー、、', '本か', '語っ', 'けーえ', '組か'] | Failed |
| regression: minimum line content | ['ゃ、', '』ーっお', '字き', '『あーけ', 'お(こ文', 'けゃ』本', '語組ゃ文'] | ['ゃ', '、』ーっ', 'お字き', '『あーけ', 'お(こ文', 'けゃ』本', '語組ゃ文'] | Failed |
| regression: minimum line content | ['う版あ', 'う。', '、っ', '』、)', '「字。あ', 'かか、『。', 'いおきゃ'] | ['う版あ', 'う', '。', '、', 'っ』、)', '「字。あ', 'かか、『。', 'いおきゃ'] | Failed |
| partial-repair probe | ['、ー', 'く」ゃ』』ー本', 'え組きけ本日', 'こ』'] | ['、ー', 'く」ゃ』』ー本', 'え組きけ本日', 'こ』'] | Passed |
| small kana prohibited at line start | ['日本語', 'かっこい', 'い'] | ['日本語', 'かっこい', 'い'] | Passed |
| period followed by bracket cannot hang | ['日本語', '文。」字', '組'] | ['日本語', '文。」字', '組'] | Passed |
| control layout | [')っ(こ', 'き文う', '字)お字', '本かー語', '本(字か'] | [')っ(こ', 'き文う', '字)お字', '本かー語', '本(字か'] | Passed |
| control layout | ['こえきかう', '「((版'] | ['こえきかう', '「((版'] | Passed |
SHA-256 / 6e1961eb654e1c82f9f9e80e12273d3bec313822d0a5fe89b6b5925eb7ec7f0a
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(x):
text, L = x
NO_START = '、。,.)」』!?ーぁぃぅぇぉっゃゅょ'
NO_END = '(「『'
HANG = '、。,.'
lines = []
pos = 0
n = len(text)
while pos < n:
end = pos + L
if end >= n:
lines.append(text[pos:])
break
if text[end] in HANG and (end + 1 >= n or text[end + 1] not in NO_START):
end += 1
else:
while end > pos + L // 2 and text[end] in NO_START:
end -= 1
while end > pos + 1 and text[end - 1] in NO_END:
end -= 1
lines.append(text[pos:end])
pos = end
return lines
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('regression: minimum line content', ['『ー』かい組ー(本」ー、、本か語っけーえ組か', 3], ['『ー』', 'かい', '組ー', '(', '本', '」ー、、', '本か', '語っ', 'けーえ', '組か']), ('regression: minimum line content', ['ゃ、』ーっお字き『あーけお(こ文けゃ』本語組ゃ文', 4], ['ゃ', '、』ーっ', 'お字き', '『あーけ', 'お(こ文', 'けゃ』本', '語組ゃ文']), ('regression: minimum line content', ['う版あう。、っ』、)「字。あかか、『。いおきゃ', 4], ['う版あ', 'う', '。', '、', 'っ』、)', '「字。あ', 'かか、『。', 'いおきゃ']), ('partial-repair probe', ['、ーく」ゃ』』ー本え組きけ本日こ』', 7], ['、ー', 'く」ゃ』』ー本', 'え組きけ本日', 'こ』']), ('small kana prohibited at line start', ['日本語かっこいい', 4], ['日本語', 'かっこい', 'い']), ('period followed by bracket cannot hang', ['日本語文。」字組', 4], ['日本語', '文。」字', '組']), ('control layout', [')っ(こき文う字)お字本かー語本(字か', 4], [')っ(こ', 'き文う', '字)お字', '本かー語', '本(字か']), ('control layout', ['こえきかう「((版', 7], ['こえきかう', '「((版'])], [('regression: minimum line content', ['文け『い、あ。「日っ」『', 3], ['文け', '『い、', 'あ。', '「', '日っ」', '『']), ('regression: minimum line content', ['け(こーっ版く」)あ)う組)けあ(う', 3], ['け', '(', 'こーっ', '版', 'く」)', 'あ)う', '組)け', 'あ(う']), ('regression: minimum line content', ['「)。文お。い組、、い)、、っ」け「あえいけ日、', 4], ['「)。文', 'お。い', '組、、', 'い', ')', '、、っ」', 'け「あえ', 'いけ日、']), ('regression: minimum line content', ['けけーうけゃ)(っ』』)ゃっ組)お', 4], ['けけーう', 'けゃ)', '(', 'っ', '』', '』)ゃっ', '組)お']), ('closing bracket pushes out', ['日本語文」字組版', 4], ['日本語', '文」字組', '版']), ('period hangs past the measure', ['日本語文。字組版', 4], ['日本語文。', '字組版']), ('control layout', ['()字「文版い字ー「版ーっ「。』組字組けあか「', 8], ['()字「文版い', '字ー「版ーっ', '「。』組字組けあ', 'か「']), ('control layout', ['『ー組い、文おけええ「本文か語、ゃお版(か語版『', 6], ['『ー組い、文', 'おけええ「本', '文か語、ゃお', '版(か語版『'])], [('regression: minimum line content', ['、あゃく文え、『か、)版」日ゃ(文『か', 3], ['、あゃ', 'く文え、', '『', 'か、)', '版」', '日ゃ', '(文', '『か']), ('regression: minimum line content', ['文え(』い。版組(あえう語』、)ー本。『組', 3], ['文え', '(』い。', '版組', '(あえ', 'う', '語', '』', '、)ー', '本。', '『組']), ('regression: minimum line content', ['字きあ)ー『、いあけーけ字字、(き。ー』」」』(', 5], ['字きあ)ー', '『、いあ', 'けーけ字字、', '(', 'き', '。', 'ー』」」』', '(']), ('regression: minimum line content', ['版(組)ーー。)日くああ本', 5], ['版', '(', '組', ')ーー。)', '日くああ本']), ('period followed by bracket cannot hang', ['日本語文。」字組', 4], ['日本語', '文。」字', '組']), ('small kana prohibited at line start', ['日本語かっこいい', 4], ['日本語', 'かっこい', 'い']), ('control layout', ['え、かけ語か「『いい日う字え', 6], ['え、かけ語か', '「『いい日う', '字え']), ('control layout', ['けいかお本。。き、こお」こ語語「か組っ「本「', 5], ['けいかお', '本。。き、', 'こお」こ語', '語「か組っ', '「本「'])], [('regression: minimum line content', ['け(こーっ版く」)あ)う組)けあ(う', 3], ['け', '(', 'こーっ', '版', 'く」)', 'あ)う', '組)け', 'あ(う']), ('regression: minimum line content', ['けこけ」組』かお字本いく』「本(い(ゃゃ)かゃ字', 3], ['けこ', 'け」', '組』か', 'お字本', 'いく』', '「本', '(い', '(', 'ゃゃ)', 'かゃ字']), ('regression: minimum line content', ['あく』』ゃあ版き「文』日ううあこ', 4], ['あ', 'く』』ゃ', 'あ版き', '「文』日', 'ううあこ']), ('regression: minimum line content', ['う版あう。、っ』、)「字。あかか、『。いおきゃ', 4], ['う版あ', 'う', '。', '、', 'っ』、)', '「字。あ', 'かか、『。', 'いおきゃ']), ('opening bracket at line end', ['日本語「文字」組版', 4], ['日本語', '「文字」', '組版']), ('period hangs past the measure', ['日本語文。字組版', 4], ['日本語文。', '字組版']), ('control layout', ['本。け本きえこ』', 5], ['本。け本き', 'えこ』']), ('control layout', ['ゃ語く)う、『こ日お組』き『日くこおおい」文ゃ『', 5], ['ゃ語く)う、', '『こ日お', '組』き『日', 'くこおお', 'い」文ゃ『'])], [('regression: minimum line content', ['文ゃー語あ。かこ本か、字、字「ゃおゃ』」、っ', 4], ['文ゃー語', 'あ。かこ', '本か、字、', '字「ゃ', 'お', 'ゃ', '』」、っ']), ('regression: minimum line content', ['字きあ)ー『、いあけーけ字字、(き。ー』」」』(', 5], ['字きあ)ー', '『、いあ', 'けーけ字字、', '(', 'き', '。', 'ー』」」』', '(']), ('regression: minimum line content', ['けけーうけゃ)(っ』』)ゃっ組)お', 4], ['けけーう', 'けゃ)', '(', 'っ', '』', '』)ゃっ', '組)お']), ('regression: minimum line content', ['語字、え『えくゃえー』』ーこ組「日『。(', 4], ['語字、え', '『えくゃ', 'え', 'ー』』ー', 'こ組「日', '『。(']), ('period hangs past the measure', ['日本語文。字組版', 4], ['日本語文。', '字組版']), ('period followed by bracket cannot hang', ['日本語文。」字組', 4], ['日本語', '文。」字', '組']), ('control layout', ['語け本日ゃ」)「字、字字', 5], ['語け本', '日ゃ」)', '「字、字字']), ('control layout', ['「『日、く)、」組)っうお。(', 6], ['「『日、', 'く)、」', '組)っうお。', '('])]]
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: minimum line content | ['『ー』', 'かい', '組ー', '(', '本', '」ー、、', '本か', '語っ', 'けーえ', '組か'] | ['『ー』', 'かい', '組ー', '(', '本', '」ー、、', '本か', '語っ', 'けーえ', '組か'] | Passed |
| regression: minimum line content | ['ゃ、', '』ーっお', '字き', '『あーけ', 'お(こ文', 'けゃ』本', '語組ゃ文'] | ['ゃ', '、』ーっ', 'お字き', '『あーけ', 'お(こ文', 'けゃ』本', '語組ゃ文'] | Failed |
| regression: minimum line content | ['う版あ', 'う。', '、っ', '』、)', '「字。あ', 'かか、『。', 'いおきゃ'] | ['う版あ', 'う', '。', '、', 'っ』、)', '「字。あ', 'かか、『。', 'いおきゃ'] | Failed |
| partial-repair probe | ['、ーく', '」ゃ』』ー本え', '組きけ本日こ』'] | ['、ー', 'く」ゃ』』ー本', 'え組きけ本日', 'こ』'] | Failed |
| small kana prohibited at line start | ['日本語', 'かっこい', 'い'] | ['日本語', 'かっこい', 'い'] | Passed |
| period followed by bracket cannot hang | ['日本語', '文。」字', '組'] | ['日本語', '文。」字', '組'] | Passed |
| control layout | [')っ(こ', 'き文う', '字)お字', '本かー語', '本(字か'] | [')っ(こ', 'き文う', '字)お字', '本かー語', '本(字か'] | Passed |
| control layout | ['こえきかう', '「((版'] | ['こえきかう', '「((版'] | Passed |
SHA-256 / 0447bd9d62ae2d829cf72f8f4360a66a81e101a57f57548e5a8db8cecb6f342f
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(x):
text, L = x
NO_START = '、。,.)」』!?ーぁぃぅぇぉっゃゅょ'
NO_END = '(「『'
HANG = '、。,.'
lines = []
pos = 0
n = len(text)
while pos < n:
end = pos + L
if end >= n:
lines.append(text[pos:])
break
if text[end] in HANG and (end + 1 >= n or text[end + 1] not in NO_START):
end += 1
else:
while end > pos + 1 and text[end] in NO_START:
end -= 1
while end > pos + 1 and text[end - 1] in NO_END:
end -= 1
lines.append(text[pos:end])
pos = end
return lines
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('regression: minimum line content', ['『ー』かい組ー(本」ー、、本か語っけーえ組か', 3], ['『ー』', 'かい', '組ー', '(', '本', '」ー、、', '本か', '語っ', 'けーえ', '組か']), ('regression: minimum line content', ['ゃ、』ーっお字き『あーけお(こ文けゃ』本語組ゃ文', 4], ['ゃ', '、』ーっ', 'お字き', '『あーけ', 'お(こ文', 'けゃ』本', '語組ゃ文']), ('regression: minimum line content', ['う版あう。、っ』、)「字。あかか、『。いおきゃ', 4], ['う版あ', 'う', '。', '、', 'っ』、)', '「字。あ', 'かか、『。', 'いおきゃ']), ('partial-repair probe', ['、ーく」ゃ』』ー本え組きけ本日こ』', 7], ['、ー', 'く」ゃ』』ー本', 'え組きけ本日', 'こ』']), ('small kana prohibited at line start', ['日本語かっこいい', 4], ['日本語', 'かっこい', 'い']), ('period followed by bracket cannot hang', ['日本語文。」字組', 4], ['日本語', '文。」字', '組']), ('control layout', [')っ(こき文う字)お字本かー語本(字か', 4], [')っ(こ', 'き文う', '字)お字', '本かー語', '本(字か']), ('control layout', ['こえきかう「((版', 7], ['こえきかう', '「((版'])], [('regression: minimum line content', ['文け『い、あ。「日っ」『', 3], ['文け', '『い、', 'あ。', '「', '日っ」', '『']), ('regression: minimum line content', ['け(こーっ版く」)あ)う組)けあ(う', 3], ['け', '(', 'こーっ', '版', 'く」)', 'あ)う', '組)け', 'あ(う']), ('regression: minimum line content', ['「)。文お。い組、、い)、、っ」け「あえいけ日、', 4], ['「)。文', 'お。い', '組、、', 'い', ')', '、、っ」', 'け「あえ', 'いけ日、']), ('regression: minimum line content', ['けけーうけゃ)(っ』』)ゃっ組)お', 4], ['けけーう', 'けゃ)', '(', 'っ', '』', '』)ゃっ', '組)お']), ('closing bracket pushes out', ['日本語文」字組版', 4], ['日本語', '文」字組', '版']), ('period hangs past the measure', ['日本語文。字組版', 4], ['日本語文。', '字組版']), ('control layout', ['()字「文版い字ー「版ーっ「。』組字組けあか「', 8], ['()字「文版い', '字ー「版ーっ', '「。』組字組けあ', 'か「']), ('control layout', ['『ー組い、文おけええ「本文か語、ゃお版(か語版『', 6], ['『ー組い、文', 'おけええ「本', '文か語、ゃお', '版(か語版『'])], [('regression: minimum line content', ['、あゃく文え、『か、)版」日ゃ(文『か', 3], ['、あゃ', 'く文え、', '『', 'か、)', '版」', '日ゃ', '(文', '『か']), ('regression: minimum line content', ['文え(』い。版組(あえう語』、)ー本。『組', 3], ['文え', '(』い。', '版組', '(あえ', 'う', '語', '』', '、)ー', '本。', '『組']), ('regression: minimum line content', ['字きあ)ー『、いあけーけ字字、(き。ー』」」』(', 5], ['字きあ)ー', '『、いあ', 'けーけ字字、', '(', 'き', '。', 'ー』」」』', '(']), ('regression: minimum line content', ['版(組)ーー。)日くああ本', 5], ['版', '(', '組', ')ーー。)', '日くああ本']), ('period followed by bracket cannot hang', ['日本語文。」字組', 4], ['日本語', '文。」字', '組']), ('small kana prohibited at line start', ['日本語かっこいい', 4], ['日本語', 'かっこい', 'い']), ('control layout', ['え、かけ語か「『いい日う字え', 6], ['え、かけ語か', '「『いい日う', '字え']), ('control layout', ['けいかお本。。き、こお」こ語語「か組っ「本「', 5], ['けいかお', '本。。き、', 'こお」こ語', '語「か組っ', '「本「'])], [('regression: minimum line content', ['け(こーっ版く」)あ)う組)けあ(う', 3], ['け', '(', 'こーっ', '版', 'く」)', 'あ)う', '組)け', 'あ(う']), ('regression: minimum line content', ['けこけ」組』かお字本いく』「本(い(ゃゃ)かゃ字', 3], ['けこ', 'け」', '組』か', 'お字本', 'いく』', '「本', '(い', '(', 'ゃゃ)', 'かゃ字']), ('regression: minimum line content', ['あく』』ゃあ版き「文』日ううあこ', 4], ['あ', 'く』』ゃ', 'あ版き', '「文』日', 'ううあこ']), ('regression: minimum line content', ['う版あう。、っ』、)「字。あかか、『。いおきゃ', 4], ['う版あ', 'う', '。', '、', 'っ』、)', '「字。あ', 'かか、『。', 'いおきゃ']), ('opening bracket at line end', ['日本語「文字」組版', 4], ['日本語', '「文字」', '組版']), ('period hangs past the measure', ['日本語文。字組版', 4], ['日本語文。', '字組版']), ('control layout', ['本。け本きえこ』', 5], ['本。け本き', 'えこ』']), ('control layout', ['ゃ語く)う、『こ日お組』き『日くこおおい」文ゃ『', 5], ['ゃ語く)う、', '『こ日お', '組』き『日', 'くこおお', 'い」文ゃ『'])], [('regression: minimum line content', ['文ゃー語あ。かこ本か、字、字「ゃおゃ』」、っ', 4], ['文ゃー語', 'あ。かこ', '本か、字、', '字「ゃ', 'お', 'ゃ', '』」、っ']), ('regression: minimum line content', ['字きあ)ー『、いあけーけ字字、(き。ー』」」』(', 5], ['字きあ)ー', '『、いあ', 'けーけ字字、', '(', 'き', '。', 'ー』」」』', '(']), ('regression: minimum line content', ['けけーうけゃ)(っ』』)ゃっ組)お', 4], ['けけーう', 'けゃ)', '(', 'っ', '』', '』)ゃっ', '組)お']), ('regression: minimum line content', ['語字、え『えくゃえー』』ーこ組「日『。(', 4], ['語字、え', '『えくゃ', 'え', 'ー』』ー', 'こ組「日', '『。(']), ('period hangs past the measure', ['日本語文。字組版', 4], ['日本語文。', '字組版']), ('period followed by bracket cannot hang', ['日本語文。」字組', 4], ['日本語', '文。」字', '組']), ('control layout', ['語け本日ゃ」)「字、字字', 5], ['語け本', '日ゃ」)', '「字、字字']), ('control layout', ['「『日、く)、」組)っうお。(', 6], ['「『日、', 'く)、」', '組)っうお。', '('])]]
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: minimum line content | ['『ー』', 'かい', '組ー', '(', '本', '」ー、、', '本か', '語っ', 'けーえ', '組か'] | ['『ー』', 'かい', '組ー', '(', '本', '」ー、、', '本か', '語っ', 'けーえ', '組か'] | Passed |
| regression: minimum line content | ['ゃ', '、』ーっ', 'お字き', '『あーけ', 'お(こ文', 'けゃ』本', '語組ゃ文'] | ['ゃ', '、』ーっ', 'お字き', '『あーけ', 'お(こ文', 'けゃ』本', '語組ゃ文'] | Passed |
| regression: minimum line content | ['う版あ', 'う', '。', '、', 'っ』、)', '「字。あ', 'かか、『。', 'いおきゃ'] | ['う版あ', 'う', '。', '、', 'っ』、)', '「字。あ', 'かか、『。', 'いおきゃ'] | Passed |
| partial-repair probe | ['、ー', 'く」ゃ』』ー本', 'え組きけ本日', 'こ』'] | ['、ー', 'く」ゃ』』ー本', 'え組きけ本日', 'こ』'] | Passed |
| small kana prohibited at line start | ['日本語', 'かっこい', 'い'] | ['日本語', 'かっこい', 'い'] | Passed |
| period followed by bracket cannot hang | ['日本語', '文。」字', '組'] | ['日本語', '文。」字', '組'] | Passed |
| control layout | [')っ(こ', 'き文う', '字)お字', '本かー語', '本(字か'] | [')っ(こ', 'き文う', '字)お字', '本かー語', '本(字か'] | Passed |
| control layout | ['こえきかう', '「((版'] | ['こえきかう', '「((版'] | Passed |
SHA-256 / 2fee675c36661f76e4814fa525cf8ad132a1461df5113ea8341491e4f61aa827
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:50.210038+00:00.
Case digest / dc855f0810835ac0be35a6a22a38b5146f344e5b4834b81f40bb9de5d3f96563