forked from keon/algorithms
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtext_justification.py
More file actions
85 lines (71 loc) · 2.6 KB
/
text_justification.py
File metadata and controls
85 lines (71 loc) · 2.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
"""
Text Justification
Given an array of words and a max width, format the text such that each line
has exactly max_width characters and is fully justified. Extra spaces are
distributed as evenly as possible with left slots getting more.
Reference: https://leetcode.com/problems/text-justification/
Complexity:
Time: O(n) where n is the total number of characters
Space: O(n)
"""
from __future__ import annotations
def text_justification(words: list[str], max_width: int) -> list[str]:
"""Justify text to a fixed width with evenly distributed spaces.
Args:
words: A list of words to justify.
max_width: The maximum width of each line.
Returns:
A list of fully justified strings.
Raises:
ValueError: If any word is longer than max_width.
Examples:
>>> text_justification(["What", "must", "be"], 16)
['What must be']
"""
result: list[str] = []
row_length = 0
row_words: list[str] = []
index = 0
is_first_word = True
while index < len(words):
while row_length <= max_width and index < len(words):
if len(words[index]) > max_width:
raise ValueError(
"there exists word whose length is larger than max_width"
)
tentative_length = row_length
row_words.append(words[index])
tentative_length += len(words[index])
if not is_first_word:
tentative_length += 1
if tentative_length > max_width:
row_words.pop()
break
row_length = tentative_length
index += 1
is_first_word = False
row = ""
if index == len(words):
for word in row_words:
row += word + " "
row = row[:-1]
row += " " * (max_width - len(row))
elif len(row_words) != 1:
extra_spaces = max_width - row_length
spaces_per_gap = extra_spaces // (len(row_words) - 1)
remaining_spaces = extra_spaces - spaces_per_gap * (len(row_words) - 1)
for word_index in range(len(row_words)):
row += row_words[word_index]
if word_index != len(row_words) - 1:
row += " " * (1 + spaces_per_gap)
if remaining_spaces > 0:
row += " "
remaining_spaces -= 1
else:
row += row_words[0]
row += " " * (max_width - len(row))
result.append(row)
row_length = 0
row_words = []
is_first_word = True
return result