|
| 1 | +/// Given an array of strings `words` and a width `maxWidth`, format the text such that each line |
| 2 | +/// has exactly `maxWidth` characters and is fully (left and right) justified. |
| 3 | +/// |
| 4 | +/// You should pack your words in a greedy approach; that is, pack as many words as you can in each |
| 5 | +/// line. Pad extra spaces `' '` when necessary so that each line has exactly `maxWidth` |
| 6 | +/// characters. |
| 7 | +/// |
| 8 | +/// Extra spaces between words should be distributed as evenly as possible. If the number of spaces |
| 9 | +/// on a line does not divide evenly between words, the empty slots on the left will be assigned |
| 10 | +/// 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 |
| 13 | +/// words. |
| 14 | +struct Solution; |
| 15 | + |
| 16 | +impl Solution { |
| 17 | + |
| 18 | + pub fn full_justify(words: Vec<String>, max_width: i32) -> Vec<String> { |
| 19 | + let max_width = max_width as usize; |
| 20 | + let n = words.len(); |
| 21 | + |
| 22 | + let mut line_len = 0; |
| 23 | + let mut start = 0; |
| 24 | + |
| 25 | + let mut results = vec![]; |
| 26 | + |
| 27 | + for i in 0..n { |
| 28 | + let word = &words[i]; |
| 29 | + let word_len = word.len(); |
| 30 | + let attempt = if line_len == 0 { |
| 31 | + word_len |
| 32 | + } else { |
| 33 | + line_len + word_len + 1 |
| 34 | + }; |
| 35 | + if attempt == max_width { |
| 36 | + // Matches Perfectly |
| 37 | + // One Space Between Words |
| 38 | + let mut line = words[start].clone(); |
| 39 | + for j in start+1..=i { |
| 40 | + line.push(' '); |
| 41 | + line.push_str(&words[j]); |
| 42 | + } |
| 43 | + results.push(line); |
| 44 | + start = i + 1; |
| 45 | + line_len = 0; |
| 46 | + } else if attempt < max_width { |
| 47 | + // Keep Going |
| 48 | + line_len = attempt; |
| 49 | + } else { |
| 50 | + // Overshot It |
| 51 | + let mut chars_len = 0; |
| 52 | + let mut count = 0; |
| 53 | + for j in start..i { |
| 54 | + chars_len += words[j].len(); |
| 55 | + count += 1; |
| 56 | + } |
| 57 | + count -= 1; |
| 58 | + let mut diff = max_width - chars_len; |
| 59 | + let mut line = words[start].clone(); |
| 60 | + for j in start+1..i { |
| 61 | + // Divide the spaces evenly between words and |
| 62 | + // push the spaces and the word. |
| 63 | + let spaces = (diff as f64 / count as f64).ceil() as usize; |
| 64 | + count -= 1; |
| 65 | + diff -= spaces; |
| 66 | + for _ in 0..spaces { |
| 67 | + line.push(' '); |
| 68 | + } |
| 69 | + line.push_str(&words[j]); |
| 70 | + } |
| 71 | + // If there's only one word in the line, there may |
| 72 | + // need to be spaces pushed at the end. |
| 73 | + for _ in 0..diff { |
| 74 | + line.push(' '); |
| 75 | + } |
| 76 | + results.push(line); |
| 77 | + start = i; |
| 78 | + line_len = word_len; |
| 79 | + } |
| 80 | + } |
| 81 | + |
| 82 | + if start < n { |
| 83 | + let mut line = words[start].clone(); |
| 84 | + line_len = words[start].len(); |
| 85 | + for j in start+1..n { |
| 86 | + line.push(' '); |
| 87 | + line.push_str(&words[j]); |
| 88 | + line_len += 1 + &words[j].len(); |
| 89 | + } |
| 90 | + if line_len < max_width { |
| 91 | + for _ in line_len..max_width { |
| 92 | + line.push(' '); |
| 93 | + } |
| 94 | + } |
| 95 | + results.push(line); |
| 96 | + } |
| 97 | + |
| 98 | + results |
| 99 | + } |
| 100 | +} |
| 101 | + |
| 102 | +#[cfg(test)] |
| 103 | +mod tests { |
| 104 | + use super::Solution; |
| 105 | + |
| 106 | + #[test] |
| 107 | + fn example_1() { |
| 108 | + let words = vec![ |
| 109 | + str!("This"), |
| 110 | + str!("is"), |
| 111 | + str!("an"), |
| 112 | + str!("example"), |
| 113 | + str!("of"), |
| 114 | + str!("text"), |
| 115 | + str!("justification.") |
| 116 | + ]; |
| 117 | + let max_width = 16; |
| 118 | + let results = Solution::full_justify(words, max_width); |
| 119 | + assert_eq!(results, vec![ |
| 120 | + "This is an", |
| 121 | + "example of text", |
| 122 | + "justification. " |
| 123 | + ]); |
| 124 | + } |
| 125 | + |
| 126 | + #[test] |
| 127 | + fn example_2() { |
| 128 | + let words = vec![ |
| 129 | + str!("What"), |
| 130 | + str!("must"), |
| 131 | + str!("be"), |
| 132 | + str!("acknowledgment"), |
| 133 | + str!("shall"), |
| 134 | + str!("be"), |
| 135 | + ]; |
| 136 | + let max_width = 16; |
| 137 | + let results = Solution::full_justify(words, max_width); |
| 138 | + assert_eq!(results, vec![ |
| 139 | + "What must be", |
| 140 | + "acknowledgment ", |
| 141 | + "shall be " |
| 142 | + ]); |
| 143 | + } |
| 144 | + |
| 145 | +} |
0 commit comments