#![warn(clippy::pedantic)] use std::{collections::HashMap, io::stdin, path::PathBuf}; use aoc::PathExt; fn find_dir_to_delete(dirs: &HashMap) -> usize { const TOTAL_SPACE: usize = 70_000_000; const REQUIRED_SPACE: usize = 30_000_000; let unused = TOTAL_SPACE - dirs[&*PathBuf::from("/")]; let to_free = REQUIRED_SPACE - unused; let mut sizes: Vec<_> = dirs.values().copied().collect(); sizes.sort_unstable(); match sizes.binary_search(&to_free) { Ok(i) | Err(i) => sizes[i], } } fn main() { let mut cwd = PathBuf::new(); cwd.push("/"); let mut dirs: HashMap = HashMap::new(); for line in stdin().lines() { let line = line.unwrap(); if let Some(command) = line.strip_prefix("$ ") { let mut args = command.split_whitespace(); if args.next().unwrap() != "cd" { continue; } match args.next().unwrap() { ".." => assert!(cwd.pop()), path => { cwd.push(path); assert!(!dirs.contains_key(&cwd)); } } } else { let size = line.split_whitespace().next().unwrap(); if size == "dir" { continue; } let size: usize = size.parse().unwrap(); for dir in cwd.parents() { *dirs.entry(dir.to_path_buf()).or_default() += size; } } } println!( "{}", dirs.values().filter(|&&s| s <= 100_000).sum::() ); println!("{}", find_dir_to_delete(&dirs)); }