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)
}