|
| 1 | +use std::collections::HashMap; |
| 2 | +use std::fs::File; |
| 3 | +use std::io::{BufRead, BufReader}; |
| 4 | + |
| 5 | +const MAX: u64 = 70_000_000; |
| 6 | +const REQUIRED: u64 = 30_000_000; |
| 7 | + |
| 8 | +fn solution(input: BufReader<File>) -> u64 { |
| 9 | + let mut total = 0; |
| 10 | + let mut dir_stack: Vec<String> = Vec::new(); |
| 11 | + let mut dir_sizes = HashMap::new(); |
| 12 | + |
| 13 | + for line_result in input.lines() { |
| 14 | + match line_result |
| 15 | + .expect("failed to parse string") |
| 16 | + .split_once(" ") |
| 17 | + .expect("failed to split line") |
| 18 | + { |
| 19 | + ("$", "ls") => { /* do nothing */ } |
| 20 | + ("dir", _dir_name) => { /* do nothing */ } |
| 21 | + ("$", cmd) => { |
| 22 | + match cmd.split_once(" ") { |
| 23 | + Some(("cd", "/")) => { |
| 24 | + dir_sizes.insert("/", 0u64); |
| 25 | + // asume `$ cd /` called only once |
| 26 | + /* do nothing */ |
| 27 | + } |
| 28 | + Some(("cd", "..")) => { |
| 29 | + if let Some(current_dir_name) = dir_stack.pop() { |
| 30 | + if let (Some(parent_dir_name), Some(current_dir_size)) = |
| 31 | + (dir_stack.last(), dir_sizes.get(¤t_dir_name as &str)) |
| 32 | + { |
| 33 | + dir_sizes |
| 34 | + .entry(parent_dir_name) |
| 35 | + .and_modify(|val| *val += current_dir_size); |
| 36 | + } |
| 37 | + } |
| 38 | + } |
| 39 | + Some(("cd", dir_name)) => { |
| 40 | + dir_sizes.insert("/", 0u64); |
| 41 | + dir_stack.push(dir_name.to_string()); |
| 42 | + } |
| 43 | + Some(val) => panic!("unhandled command: {:?}", val), |
| 44 | + None => panic!("failed to parse command"), |
| 45 | + } |
| 46 | + } |
| 47 | + (raw_num, _file_name) => { |
| 48 | + let file_size = raw_num.parse::<u64>().expect("failed to parse file line"); |
| 49 | + total += file_size; |
| 50 | + if let Some(current_dir_name) = dir_stack.last() { |
| 51 | + dir_sizes |
| 52 | + .entry(current_dir_name) |
| 53 | + .and_modify(|val| *val += file_size); |
| 54 | + } |
| 55 | + } |
| 56 | + } |
| 57 | + } |
| 58 | + |
| 59 | + *dir_sizes |
| 60 | + .values() |
| 61 | + .filter(|&&size| MAX - (total - size) >= REQUIRED) |
| 62 | + .min() |
| 63 | + .expect("solution not found") |
| 64 | +} |
| 65 | + |
| 66 | +fn main() { |
| 67 | + let test_file = File::open("./07/test.txt").unwrap(); |
| 68 | + assert_eq!(solution(BufReader::new(test_file)), 24933642); |
| 69 | + |
| 70 | + let input_file = File::open("./07/input.txt").unwrap(); |
| 71 | + println!("solution: {}", solution(BufReader::new(input_file))); // answer 1513699 |
| 72 | +} |
0 commit comments