Skip to content

Commit cd82206

Browse files
committed
feat(string): text justification
1 parent 5ab6a1f commit cd82206

File tree

3 files changed

+146
-0
lines changed

3 files changed

+146
-0
lines changed
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
# Text Justification
2+
3+
Given an array of strings words and a width maxWidth, format the text such that each line has exactly maxWidth
4+
characters and is fully (left and right) justified.
5+
6+
You should pack your words in a greedy approach; that is, pack as many words as you can in each line. Pad extra
7+
spaces ' ' when necessary so that each line has exactly maxWidth characters.
8+
9+
Extra spaces between words should be distributed as evenly as possible. If the number of spaces on a line does not
10+
divide evenly between words, the empty slots on the left will be assigned more spaces than the slots on the right.
11+
12+
For the last line of text, it should be left-justified, and no extra space is inserted between words.
13+
14+
Note:
15+
16+
A word is defined as a character sequence consisting of non-space characters only.
17+
Each word's length is guaranteed to be greater than 0 and not exceed maxWidth.
18+
The input array words contains at least one word.
19+
20+
```text
21+
Example 1:
22+
23+
Input: words = ["This", "is", "an", "example", "of", "text", "justification."], maxWidth = 16
24+
Output:
25+
[
26+
"This is an",
27+
"example of text",
28+
"justification. "
29+
]
30+
```
31+
32+
```text
33+
Example 2:
34+
35+
Input: words = ["What","must","be","acknowledgment","shall","be"], maxWidth = 16
36+
Output:
37+
[
38+
"What must be",
39+
"acknowledgment ",
40+
"shall be "
41+
]
42+
Explanation: Note that the last line is "shall be " instead of "shall be", because the last line must be
43+
left-justified instead of fully-justified.
44+
Note that the second line is also left-justified because it contains only one word.
45+
```
46+
47+
```text
48+
Example 3:
49+
50+
Input:
51+
words = ["Science","is","what","we","understand","well","enough","to","explain","to","a","computer.","Art","is","everything","else","we","do"],
52+
maxWidth = 20
53+
Output:
54+
[
55+
"Science is what we",
56+
"understand well",
57+
"enough to explain to",
58+
"a computer. Art is",
59+
"everything else we",
60+
"do "
61+
]
62+
```
63+
64+
## Related Topics
65+
66+
- Array
67+
- String
68+
- Simulation
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
from typing import List
2+
3+
4+
def full_justify(words: List[str], max_width: int) -> List[str]:
5+
"""
6+
How does it work? This uses a round-robin. The following line implements the round-robin logic:
7+
for i in range(maxWidth - num_of_letters):
8+
cur[i%(len(cur)-1 or 1)] += ' '
9+
10+
What does this line do? Once you determine that there are only k words that can fit on a given line, you know what
11+
the total length of those words is num_of_letters. Then the rest are spaces, and there are
12+
(max_width - num_of_letters) of spaces. The "or 1" part is for dealing with the edge case len(cur) == 1.
13+
14+
Args:
15+
words (list): words to fully justify
16+
max_width (int): width of each line
17+
Returns:
18+
list: list of justified words
19+
"""
20+
res, cur, num_of_letters = [], [], 0
21+
for w in words:
22+
if num_of_letters + len(w) + len(cur) > max_width:
23+
for i in range(max_width - num_of_letters):
24+
cur[i % (len(cur) - 1 or 1)] += ' '
25+
res.append(''.join(cur))
26+
cur, num_of_letters = [], 0
27+
cur += [w]
28+
num_of_letters += len(w)
29+
return res + [' '.join(cur).ljust(max_width)]
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import unittest
2+
from . import full_justify
3+
4+
5+
class FullJustifyTestCase(unittest.TestCase):
6+
def test_1(self):
7+
"""words = ["This", "is", "an", "example", "of", "text", "justification."], maxWidth = 16"""
8+
words = ["This", "is", "an", "example", "of", "text", "justification."]
9+
max_width = 16
10+
expected = [
11+
"This is an",
12+
"example of text",
13+
"justification. "
14+
]
15+
actual = full_justify(words, max_width)
16+
self.assertListEqual(expected, actual)
17+
18+
def test_2(self):
19+
"""words = ["What","must","be","acknowledgment","shall","be"], maxWidth = 16"""
20+
words = ["What", "must", "be", "acknowledgment", "shall", "be"]
21+
max_width = 16
22+
expected = [
23+
"What must be",
24+
"acknowledgment ",
25+
"shall be "
26+
]
27+
actual = full_justify(words, max_width)
28+
self.assertListEqual(expected, actual)
29+
30+
def test_3(self):
31+
"""words = ["Science","is","what","we","understand","well","enough","to","explain","to","a","computer.","Art",
32+
"is","everything","else","we","do"], maxWidth = 20"""
33+
words = ["Science", "is", "what", "we", "understand", "well", "enough", "to", "explain", "to", "a", "computer.",
34+
"Art", "is", "everything", "else", "we", "do"]
35+
max_width = 20
36+
expected = [
37+
"Science is what we",
38+
"understand well",
39+
"enough to explain to",
40+
"a computer. Art is",
41+
"everything else we",
42+
"do "
43+
]
44+
actual = full_justify(words, max_width)
45+
self.assertListEqual(expected, actual)
46+
47+
48+
if __name__ == '__main__':
49+
unittest.main()

0 commit comments

Comments
 (0)