diff options
author | Aria <me@aria.rip> | 2023-01-02 21:58:56 +0000 |
---|---|---|
committer | Aria <me@aria.rip> | 2023-01-02 21:58:56 +0000 |
commit | 5eb58ad076f2cd435b11b140820da224b60b73d5 (patch) | |
tree | 2a67939595fbf993ff04f69b9cd3f0aa20827d96 /2022/src/day07.rs |
initial commit
Diffstat (limited to '2022/src/day07.rs')
-rw-r--r-- | 2022/src/day07.rs | 110 |
1 files changed, 110 insertions, 0 deletions
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<Self::Item> { + 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()) + } + } +} |