[TASK] Optimized Day 7: removed directory names

This commit is contained in:
2022-12-10 16:53:36 +01:00
parent 8754356dbc
commit f6132bbf24

View File

@@ -6,12 +6,9 @@ use super::util;
#[derive(Debug)] #[derive(Debug)]
enum FileSystemEntry { enum FileSystemEntry {
File { File {
name: String,
size: usize size: usize
}, },
Directory { Directory
name: String,
}
} }
#[derive(Debug)] #[derive(Debug)]
@@ -38,14 +35,11 @@ impl Day7 {
while let Some(result_line) = lines_iter.peek() { while let Some(result_line) = lines_iter.peek() {
if !result_line.starts_with("$") { if !result_line.starts_with("$") {
if result_line.starts_with("dir") { if result_line.starts_with("dir") {
result.push(FileSystemEntry::Directory { result.push(FileSystemEntry::Directory)
name: result_line.split_whitespace().skip(1).next().unwrap().to_string()
})
} else { } else {
let mut result_split = result_line.split_whitespace(); let mut result_split = result_line.split_whitespace();
result.push(FileSystemEntry::File { result.push(FileSystemEntry::File {
size: result_split.next().unwrap().parse::<usize>().unwrap(), size: result_split.next().unwrap().parse::<usize>().unwrap()
name: result_split.next().unwrap().to_owned()
}); });
} }
lines_iter.next(); lines_iter.next();
@@ -70,42 +64,62 @@ impl Day7 {
} }
} }
fn calculate_dir_sizes(&self) -> Vec<(Vec<String>, usize)> { fn calculate_dir_sizes(&self) -> Vec<usize> {
let mut dir_stack = Vec::new();
let mut size_stack: Vec<usize> = Vec::new(); let mut size_stack: Vec<usize> = Vec::new();
size_stack.push(0); size_stack.push(0);
let mut dir_sizes: Vec<(Vec<String>, usize)> = Vec::new(); let mut dir_sizes: Vec<usize> = Vec::new();
for command in &self.commands { 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. // In the first pass, we only count files directly under it, then in the final pass we also include children.
match command { match command {
Command::CD { target } => { Command::CD { target } => {
if 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 == "/" { } 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 { } else {
dir_stack.push(target.clone());
size_stack.push(0); size_stack.push(0);
} }
} }
Command::LS { result } => { Command::LS { result } => {
let file_size: usize = result.iter() 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(); .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(); let root_size: usize = size_stack.last().unwrap().to_owned();
// dir_sizes.iter() dir_sizes.push(root_size);
// .filter_map(|(dir, size)| if dir.len() == 1 { Some(size) } else { None })
// .sum::<usize>();
dir_sizes.push((Vec::new(), root_size));
println!("{:?}", dir_sizes.iter().map(|d| format!("/{}: {}", d.0.join("/"), d.1)).collect::<Vec<String>>());
dir_sizes dir_sizes
} }
fn move_to_root(dir_sizes: &mut Vec<usize>, size_stack: &mut Vec<usize>) {
// 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<usize>, size_stack: &mut Vec<usize>) {
// 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<usize>, size: usize) {
if let Some(last) = size_stack.last_mut() {
*last += size;
}
}
} }
impl DaySolver for Day7 { impl DaySolver for Day7 {
@@ -116,42 +130,18 @@ impl DaySolver for Day7 {
let dir_sizes = self.calculate_dir_sizes(); let dir_sizes = self.calculate_dir_sizes();
return dir_sizes.iter() return dir_sizes.iter()
.filter_map(|(_, size)| if size <= &100000usize { Some(size)} else { None }) .filter(|size| size <= &&100000usize)
.sum::<usize>().to_string(); .sum::<usize>().to_string();
} }
fn solve_part2(&mut self) -> String { fn solve_part2(&mut self) -> String {
let dir_sizes = self.calculate_dir_sizes(); 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); let min_delete_size = 30_000_000usize - (70_000_000usize - root_size);
return dir_sizes.iter().map(|d| d.1) return dir_sizes.iter()
.filter(|s| s > &min_delete_size) .filter(|s| s > &&min_delete_size)
.min().unwrap().to_string(); .min().unwrap().to_string();
} }
} }
fn move_to_root(dir_stack: &mut Vec<String>, dir_sizes: &mut Vec<(Vec<String>, usize)>, size_stack: &mut Vec<usize>) {
while !dir_stack.is_empty() {
move_up_dir(dir_sizes, dir_stack, size_stack);
}
}
fn move_up_dir(dir_sizes: &mut Vec<(Vec<String>, usize)>, dir_stack: &mut Vec<String>, size_stack: &mut Vec<usize>) {
// 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<usize>, size: usize) {
if let Some(last) = size_stack.last_mut() {
*last += size;
}
}