import fileinput from typing import Iterable, Optional class Directory(): def __init__(self, parent = None): self.dirs = {} self.files = {} self.parent = parent def get_size(self) -> int: return sum(self.files.values()) + sum([d.get_size() for d in self.dirs.values()]) def print_tree(self, depth = 0): if depth == 0: print("/") for d, v in self.dirs.items(): print(" "*(depth+1) + d) v.print_tree(depth+1) for f, size in self.files.items(): print(" "*(depth+1) + f + " " + str(size)) def walk(self): output = [self] for d in self.dirs.values(): output += d.walk() return output def parse(lines: Iterable[str]) -> Directory: root = None cwd = None for line in map(lambda x: x.strip(), lines): if line.startswith("$ "): # command if line == "$ cd /": root = Directory() cwd = root elif line == "$ cd ..": cwd = cwd.parent elif line.startswith("$ cd"): cwd = cwd.dirs[line.split(" ")[2]] elif line.startswith("$ ls"): pass elif line.startswith("dir "): # dir name = line.split(' ')[1] cwd.dirs[name] = Directory(cwd) else: # file size, name = line.split(' ') cwd.files[name] = int(size) return root def solve(lines: Iterable[str]) -> int: root = parse(lines) output = 0 for d in root.walk(): size = d.get_size() if size <= 100000: output += size return output def solveb(lines: Iterable[str]) -> int: TOTAL = 70000000 GOAL = 30000000 root = parse(lines) current = root.get_size() free = TOTAL - current to_free = GOAL - free print(f"Current: {current}") print(f"To free: {to_free}") candidates = [d for d in root.walk() if d.get_size() >= to_free] return min(map(lambda x: x.get_size(), candidates)) if __name__ == "__main__": parse(fileinput.input()).print_tree() print(solve(fileinput.input())) print(solveb(fileinput.input()))