[TASK] Optimized Day 7: removed directory names
This commit is contained in:
92
src/day7.rs
92
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::<usize>().unwrap(),
|
||||
name: result_split.next().unwrap().to_owned()
|
||||
size: result_split.next().unwrap().parse::<usize>().unwrap()
|
||||
});
|
||||
}
|
||||
lines_iter.next();
|
||||
@@ -70,42 +64,62 @@ impl Day7 {
|
||||
}
|
||||
}
|
||||
|
||||
fn calculate_dir_sizes(&self) -> Vec<(Vec<String>, usize)> {
|
||||
let mut dir_stack = Vec::new();
|
||||
fn calculate_dir_sizes(&self) -> Vec<usize> {
|
||||
let mut size_stack: Vec<usize> = Vec::new();
|
||||
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 {
|
||||
|
||||
// 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::<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.push(root_size);
|
||||
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 {
|
||||
@@ -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::<usize>().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<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;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user