Kerning line fit
MediumOnline Assessment
Find which lines of a text block are too wide once the font's kerning and ligatures are applied.
A font is described by a glyph table and a kerning list. Glyph entries look like "a=5": the character a is 5 units wide (the space is written " =3"). An entry whose key has two letters, such as "fi=7", is a ligature: those two letters, side by side, are drawn as one glyph of that width. A character that has no entry is default_width wide.
To measure a line:
- Remove every space at the end of the line. Spaces at the start or in the middle stay and are measured like any other character.
- Read the remaining text from left to right. At each position, if that character and the next one form a ligature, take them as a single glyph; otherwise take one character as a glyph. (So with ligatures
fiandff, the textffiis the glyphfffollowed byi.) - The line's width is the sum of its glyph widths plus the kerning adjustment for every pair of neighbouring glyphs. For a pair, the *left letter* is the last character of the left glyph and the *right letter* is the first character of the right glyph.
Kerning entries look like "AV=-3" (exact pair), "A*=-1" (any letter after A) or "*V=-2" (any letter before V); the pair may include a space. For a given pair of letters use the first rule that applies: the exact entry, otherwise the L* entry for the left letter, otherwise the *R entry for the right letter, otherwise 0. If the same entry key is listed more than once, the last one listed is the one that counts. Kerning never applies inside a ligature.
A line is overfull when its width is strictly greater than column_width.
Input: glyphs (list of strings), kerning (list of strings), default_width (integer), column_width (integer), lines (list of strings).
Output: a list with one [line_index, overflow] pair (0-based index, width - column_width) for every overfull line, ordered by overflow, largest first, and by line index, smallest first, when overflows are equal. Return [] if no line is overfull.
Example 1
- Input:
- [["A=7","V=7","T=6","o=5","e=5","f=4","i=3","c=5"," =3","fi=7","ff=8"],["AV=-3","A*=-1","*V=-2","T*=-1","of=-1","fi=-2"],5,17,["AVA","ATV ","Voe"]]
- Output:
- [[0,1],[1,1]]
- Explanation
- Column width 17.
AVA: glyph widths 7+7+7 = 21. The pair A,V has an exact rule (-3), which beats the wildcardsA*(-1) and*V(-2); the pair V,A has no rule. Width 18, so it overflows by 1.ATV: trailing spaces are dropped, widths 7+6+7 = 20; pair A,T usesA*(-1); pair T,V has two wildcard rules,T*(-1) and*V(-2), and the one fixing the left character wins, so -1. Width 18, overflow 1.Voe: 7+5+5 = 17 with no rules, exactly the column width, so it fits.
Example 2
- Input:
- [["A=7","V=7","T=6","o=5","e=5","f=4","i=3","c=5"," =3","fi=7","ff=8"],["AV=-3","A*=-1","*V=-2","T*=-1","of=-1","fi=-2"],5,20,["office","fief"]]
- Output:
- [[0,3]]
- Explanation
- Column width 20.
officeis read left to right:o, thenff(a ligature in the glyph table), theni,c,e. Widths 5+8+3+5+5 = 26. The pair (o, ff) uses the right glyph's first letter:of= -1. The pair (ff, i) uses the left glyph's last letter, so it is the pair f,i:fi= -2 (thefiligature is not formed here becauseffwas taken first). Width 23, overflow 3.fiefstarts with thefiligature: 7+5+4 = 16, no applicable rules, and it fits.
Example 3
- Input:
- [["A=7","V=7"," =3"],["A*=-1","A*=-4","*V=-2","*V=1"],5,10,[" AV","AVA","VV",""," "]]
- Output:
- [[1,7],[0,6],[2,5]]
- Explanation
- Column width 10. When a rule is listed twice the last one wins, so
A*is -4 and*Vis +1.AVkeeps its leading spaces: 3+3+7+7 = 20, pair A,V usesA*(-4), total 16, overflow 6.AVA: 21 - 4 = 17, overflow 7.VV: 14, pair V,V uses*V(+1), total 15, overflow 5. The empty line and the line of spaces have width 0. Sorted by overflow, largest first: lines 1, 0, 2.
Constraints
0 <= len(lines) <= 60, and every line has at most120characters- text consists of letters and spaces only; no character is
=or* - every width is an integer with
1 <= width <= 100; every kerning amount is an integer between-20and20 1 <= default_width <= 100;1 <= column_width <= 3000