import re from string import ascii_lowercase, ascii_uppercase, digits EXAMPLE = """ $ cd / $ ls dir a 14848514 b.txt 8504156 c.dat dir d $ cd a $ ls dir e 29116 f 2557 g 62596 h.lst $ cd e $ ls 584 i $ cd .. $ cd .. $ cd d $ ls 4060174 j 8033020 d.log 5626152 d.ext 7214296 k """ def clean(text: str) -> list[str]: return list(filter(lambda l: l.strip() != "", text.splitlines())) def solve(lines: list[str]): sizes = {} res = 0 current_dir = () for line in lines: if line.startswith("$ cd"): c = line.replace("$ cd ", "").strip() if c == "..": current_dir = tuple(list(current_dir)[:-1]) else: current_dir = tuple(list(current_dir) + [c]) elif line[0] in digits: size, _ = line.split() size = int(size) try: sizes[current_dir] += size except KeyError: sizes[current_dir] = size for i in range(1, len(current_dir)): outer_dir = tuple(list(current_dir)[:-i]) try: sizes[outer_dir] += size except KeyError: sizes[outer_dir] = size for _, size in sizes.items(): if size <= 100000: res += size # 23:50 return res def solve2(lines: list[str]): sizes = {} res = 0 current_dir = () for line in lines: if line.startswith("$ cd"): c = line.replace("$ cd ", "").strip() if c == "..": current_dir = tuple(list(current_dir)[:-1]) else: current_dir = tuple(list(current_dir) + [c]) elif line[0] in digits: size, _ = line.split() size = int(size) try: sizes[current_dir] += size except KeyError: sizes[current_dir] = size for i in range(1, len(current_dir)): outer_dir = tuple(list(current_dir)[:-i]) try: sizes[outer_dir] += size except KeyError: sizes[outer_dir] = size total_space = 70000000 unused_space = 30000000 used_space = sizes[("/",)] res = 2**32 for _, size in sizes.items(): if total_space - used_space + size >= unused_space and size < res: res = size # 27:55 return res def main(): example = clean(EXAMPLE) print("Example 1:", solve(example)) data = clean(open("d7.txt").read()) print("Solution 1:", solve(data)) example = clean(EXAMPLE) print("Example 2:", solve2(example)) data = clean(open("d7.txt").read()) print("Solution 2:", solve2(data)) if __name__ == "__main__": main()