Skip to content

Instantly share code, notes, and snippets.

@AnthonyMikh
Created October 10, 2020 10:49
Show Gist options
  • Save AnthonyMikh/9bd333ec44bd4d1ba72eec1a8175809e to your computer and use it in GitHub Desktop.
Save AnthonyMikh/9bd333ec44bd4d1ba72eec1a8175809e to your computer and use it in GitHub Desktop.
Text justification (solution for Leetcode problem). Copid from submission verbatim.
impl Solution {
pub fn full_justify(words: Vec<String>, max_width: i32) -> Vec<String> {
let mut ret = Vec::new();
let width = max_width as usize;
let mut words = &words[..];
while let Some((first, rest)) = split_by_width(&mut words, width) {
if words.is_empty() {
ret.push(pack_left_justified(width, first, rest));
} else{
ret.push(pack(width, first, rest));
}
}
ret
}
}
fn split_by_width<'w>(words: &mut &'w [String], max_width: usize) -> Option<(&'w str, &'w [String])> {
let (first, rest) = words.split_first()?;
let mut total_width = first.len();
let taken = rest.iter()
.map(|word| {
total_width += word.len() + 1;
total_width
})
.take_while(|&width| width <= max_width)
.count() + 1;
let ret = &words[1..taken];
*words = &words[taken..];
Some((first, ret))
}
fn distribute_spaces(total: usize, partitions: usize) -> impl Iterator<Item = usize> {
let per_part = total / partitions;
let mut excess = total % partitions;
std::iter::repeat(()).map(move |_| {
if excess == 0 {
per_part
} else{
excess -= 1;
per_part + 1
}
})
}
fn pack(width: usize, first: &str, rest: &[String]) -> String {
let mut ret = String::with_capacity(width);
ret.push_str(first);
if rest.is_empty() {
for _ in 0..width - first.len() {
ret.push(' ');
}
return ret;
}
let total_len = first.len() + rest.iter().map(|w| w.len()).sum::<usize>();
for (sp, word) in distribute_spaces(width - total_len, rest.len()).zip(rest) {
for _ in 0..sp {
ret.push(' ');
}
ret.push_str(word);
}
ret
}
fn pack_left_justified(width: usize, first: &str, rest: &[String]) -> String {
let mut ret = String::with_capacity(width);
ret.push_str(first);
if rest.is_empty() {
for _ in 0..width - first.len() {
ret.push(' ');
}
return ret;
}
let justified_len = first.len() + rest.iter().map(|w| w.len() + 1).sum::<usize>();
for word in rest {
ret.push(' ');
ret.push_str(word);
}
for _ in 0..width - justified_len {
ret.push(' ');
}
ret
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment