use std::{io::{self, Read}, collections::{HashMap, LinkedList}};

fn main() {
    let mut stdin = io::stdin();
    let mut buf: String = String::new();
    stdin.read_to_string(&mut buf).unwrap();
    let lines: Vec<&str> = buf.split("\n").collect();
    let mut dir: Vec<&str> = vec![""];
    let mut sizes: HashMap<String, u32> = HashMap::new();
    let mut i = 0;
    let mut loose_ends: LinkedList<(String, usize, u32)> = LinkedList::new();
    while i < lines.len() - 1 {
        println!("{}\t{}", i, lines[i]);
        let split: Vec<&str> = lines[i].split(" ").collect();
        i += 1;
        
        if split[0] == "$" {
            match split[1] {
                "cd" => {
                    match split[2] {
                        ".." => { dir.pop(); }
                        "/" => { dir.clear(); dir.push(""); }
                        x => { dir.push(x); }
                    }
                }
                "ls" => {
                    let (name, line, size) = dir_listing(&lines, &mut sizes, (dir.join("/"), i, 0));
                    if line >= lines.len() || lines[line].chars().next() == Some('$') {
                        sizes.insert(name, size);
                    } else {
                        loose_ends.push_back((name, line, size));
                    }
                    i = line;
                }
                _ => panic!("???")
            }
        }
    }

    while !loose_ends.is_empty() {
        let end = loose_ends.pop_front().unwrap();
        let (name, line, size) = dir_listing(&lines, &mut sizes, end);
        if line >= lines.len() || lines[line].chars().next() == Some('$') {
            sizes.insert(name, size);
        } else {
            loose_ends.push_back((name, line, size));
        }
    }

    for (k, a) in sizes.clone() {
        println!("{}  {}", a, k);
    }

    let total_size = sizes.get(&"".to_string()).unwrap();
    let needed_delete = total_size - 40_000_000;
    println!("total {}, need {}", total_size, needed_delete);

    let enough_to_delete: Vec<u32> = sizes.iter().map(|(k, v)| *v)
        .filter(|v| *v >= needed_delete).collect();
    println!("{:?}", enough_to_delete);
}

fn dir_listing<'a>(lines: &Vec<&str>, sizes: &mut HashMap<String, u32>, (name, mut line, mut size): (String, usize, u32)) -> (String, usize, u32) {
    while lines[line].chars().next().unwrap() != '$' {
        let split: Vec<&str> = lines[line].split(" ").collect();
        match split[0] {
            "dir" => {
                if sizes.contains_key(&format!("{}/{}", name, split[1])) {
                    size += sizes.get(&format!("{}/{}", name, split[1])).unwrap();
                } else {
                    return (name, line, size);
                }
            }
            x => {
                let s: u32 = x.parse::<>().unwrap();
                size += s;
            }
        }
        line += 1;
        if line >= lines.len() { break; }
    }
    (name, line, size)
}