From f6132bbf24140731296ebd66b17951d0a9e32b1b Mon Sep 17 00:00:00 2001 From: Bas Dado Date: Sat, 10 Dec 2022 16:53:36 +0100 Subject: [PATCH] [TASK] Optimized Day 7: removed directory names --- src/day7.rs | 92 ++++++++++++++++++++++++----------------------------- 1 file changed, 41 insertions(+), 51 deletions(-) diff --git a/src/day7.rs b/src/day7.rs index 6f824ee..6a9cb78 100644 --- a/src/day7.rs +++ b/src/day7.rs @@ -6,12 +6,9 @@ use super::util; #[derive(Debug)] enum FileSystemEntry { File { - name: String, size: usize }, - Directory { - name: String, - } + Directory } #[derive(Debug)] @@ -38,14 +35,11 @@ impl Day7 { while let Some(result_line) = lines_iter.peek() { if !result_line.starts_with("$") { if result_line.starts_with("dir") { - result.push(FileSystemEntry::Directory { - name: result_line.split_whitespace().skip(1).next().unwrap().to_string() - }) + result.push(FileSystemEntry::Directory) } else { let mut result_split = result_line.split_whitespace(); result.push(FileSystemEntry::File { - size: result_split.next().unwrap().parse::().unwrap(), - name: result_split.next().unwrap().to_owned() + size: result_split.next().unwrap().parse::().unwrap() }); } lines_iter.next(); @@ -70,42 +64,62 @@ impl Day7 { } } - fn calculate_dir_sizes(&self) -> Vec<(Vec, usize)> { - let mut dir_stack = Vec::new(); + fn calculate_dir_sizes(&self) -> Vec { let mut size_stack: Vec = Vec::new(); size_stack.push(0); - let mut dir_sizes: Vec<(Vec, usize)> = Vec::new(); + let mut dir_sizes: Vec = Vec::new(); for command in &self.commands { // In the first pass, we only count files directly under it, then in the final pass we also include children. match command { Command::CD { target } => { if target == ".." { - move_up_dir(&mut dir_sizes, &mut dir_stack, &mut size_stack); + Day7::move_up_dir(&mut dir_sizes, &mut size_stack); } else if target == "/" { - move_to_root(&mut dir_stack, &mut dir_sizes, &mut size_stack) + Day7::move_to_root(&mut dir_sizes, &mut size_stack); } else { - dir_stack.push(target.clone()); size_stack.push(0); } } Command::LS { result } => { let file_size: usize = result.iter() - .map(|f| if let FileSystemEntry::File { name: _, size } = f { size.to_owned() } else { 0usize }) + .map(|f| if let FileSystemEntry::File { size } = f { size.to_owned() } else { 0usize }) .sum(); - increment_last(&mut size_stack, file_size); + Day7::increment_last(&mut size_stack, file_size); } } } - move_to_root(&mut dir_stack, &mut dir_sizes, &mut size_stack); + Day7::move_to_root(&mut dir_sizes, &mut size_stack); let root_size: usize = size_stack.last().unwrap().to_owned(); - // dir_sizes.iter() - // .filter_map(|(dir, size)| if dir.len() == 1 { Some(size) } else { None }) - // .sum::(); - dir_sizes.push((Vec::new(), root_size)); - println!("{:?}", dir_sizes.iter().map(|d| format!("/{}: {}", d.0.join("/"), d.1)).collect::>()); + dir_sizes.push(root_size); dir_sizes } + + + fn move_to_root(dir_sizes: &mut Vec, size_stack: &mut Vec) { + // Note that the size stack must always have at least one entry left (for the root) + while size_stack.len() > 1 { + Day7::move_up_dir(dir_sizes, size_stack); + } + } + + + fn move_up_dir(dir_sizes: &mut Vec, size_stack: &mut Vec) { + // If we leave the directory, we should have collected all sizes of subdirs + dir_sizes.push(size_stack.last().unwrap().to_owned()); + // We also need to add the child size to the size of the "parent" + if let Some(child_size) = size_stack.pop() { + Day7::increment_last(size_stack, child_size); + } else { + panic!("I kind of expected to always have a child size?"); + } + } + + fn increment_last(size_stack: &mut Vec, size: usize) { + if let Some(last) = size_stack.last_mut() { + *last += size; + } + } } impl DaySolver for Day7 { @@ -116,42 +130,18 @@ impl DaySolver for Day7 { let dir_sizes = self.calculate_dir_sizes(); return dir_sizes.iter() - .filter_map(|(_, size)| if size <= &100000usize { Some(size)} else { None }) + .filter(|size| size <= &&100000usize) .sum::().to_string(); } fn solve_part2(&mut self) -> String { let dir_sizes = self.calculate_dir_sizes(); - let root_size = dir_sizes.last().unwrap().1; + let root_size = dir_sizes.last().unwrap(); let min_delete_size = 30_000_000usize - (70_000_000usize - root_size); - return dir_sizes.iter().map(|d| d.1) - .filter(|s| s > &min_delete_size) + return dir_sizes.iter() + .filter(|s| s > &&min_delete_size) .min().unwrap().to_string(); } } -fn move_to_root(dir_stack: &mut Vec, dir_sizes: &mut Vec<(Vec, usize)>, size_stack: &mut Vec) { - while !dir_stack.is_empty() { - move_up_dir(dir_sizes, dir_stack, size_stack); - } -} - - -fn move_up_dir(dir_sizes: &mut Vec<(Vec, usize)>, dir_stack: &mut Vec, size_stack: &mut Vec) { - // If we leave the directory, we should have collected all sizes of subdirs - dir_sizes.push((dir_stack.to_owned(), size_stack.last().unwrap().to_owned())); - dir_stack.pop(); - // We also need to add the child size to the size of the "parent" - if let Some(child_size) = size_stack.pop() { - increment_last(size_stack, child_size); - } else { - println!("I kind of expected to always have a child size?? @ {:?}", dir_stack); - } -} - -fn increment_last(size_stack: &mut Vec, size: usize) { - if let Some(last) = size_stack.last_mut() { - *last += size; - } -}