#![warn(clippy::pedantic)]

use std::{collections::HashMap, io::stdin, path::PathBuf};

use aoc::PathExt;

fn find_dir_to_delete(dirs: &HashMap<PathBuf, usize>) -> 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<PathBuf, usize> = 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::<usize>()
    );

    println!("{}", find_dir_to_delete(&dirs));
}
