From 5eb58ad076f2cd435b11b140820da224b60b73d5 Mon Sep 17 00:00:00 2001 From: Aria Date: Mon, 2 Jan 2023 21:58:56 +0000 Subject: initial commit --- 2022/src/day07.rs | 110 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 110 insertions(+) create mode 100644 2022/src/day07.rs (limited to '2022/src/day07.rs') diff --git a/2022/src/day07.rs b/2022/src/day07.rs new file mode 100644 index 0000000..88bb647 --- /dev/null +++ b/2022/src/day07.rs @@ -0,0 +1,110 @@ +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()) + } + } +} -- cgit v1.2.3