mod utils; use utils::read_input; fn main() { let input = read_input(); let mut unused = 0; let mut sum_under_threshold = 0; for size in DirectorySizes::new(&input) { if size < 100_000 { sum_under_threshold += size; } unused = 70_000_000 - size; } println!("Part 1: {}", sum_under_threshold); let deficit = 30_000_000 - unused; println!( "Part 2: {}", DirectorySizes::new(&input) .filter(|x| *x > deficit) .min() .unwrap() ); } struct DirectorySizes<'a> { lines: std::str::Lines<'a>, directory_stack: [usize; 64], stack_top: usize, } impl<'a> DirectorySizes<'a> { fn new(input: &'a str) -> Self { let mut lines = input.lines(); assert_eq!(lines.next(), Some("$ cd /")); DirectorySizes { lines, directory_stack: [0; 64], stack_top: 0, } } } impl Iterator for DirectorySizes<'_> { type Item = usize; fn next(&mut self) -> Option { for line in self.lines.by_ref() { let line: Line = line.into(); match line { Line::Cd(up) => { if up { self.directory_stack[self.stack_top - 1] += self.directory_stack[self.stack_top]; self.stack_top -= 1; return Some(self.directory_stack[self.stack_top + 1]); } else { self.stack_top += 1; self.directory_stack[self.stack_top] = 0; } } Line::FileSize(size) => { self.directory_stack[self.stack_top] += size; } Line::Ls => (), Line::Dir => (), }; } if self.stack_top > 0 { self.directory_stack[self.stack_top - 1] += self.directory_stack[self.stack_top]; self.stack_top -= 1; Some(self.directory_stack[self.stack_top + 1]) } else if self.directory_stack[0] != 0 { Some(std::mem::replace(&mut self.directory_stack[0], 0)) } else { None } } } #[derive(Debug, Clone, Copy)] enum Line { /// True = .., False = other Cd(bool), Ls, FileSize(usize), Dir, } impl From<&str> for Line { fn from(value: &str) -> Self { if value.starts_with("$ cd ") { let mut args = value.split("cd "); args.next().unwrap(); Line::Cd(args.next().unwrap() == "..") } else if value.starts_with("$ ls") { Line::Ls } else if value.starts_with("dir") { Line::Dir } else { let num_index = value.chars().take_while(|chr| chr.is_numeric()).count(); Line::FileSize(value[..num_index].parse().unwrap()) } } }