81 lines
2.0 KiB
Python
81 lines
2.0 KiB
Python
import sys
|
|
from pathlib import Path
|
|
|
|
lines = sys.stdin.read().splitlines()
|
|
|
|
# we are going to use Path to create path and go up/down in the file tree since it
|
|
# implements everything we need
|
|
#
|
|
# we can use .resolve() to get normalized path, although this will add C:\ to all paths
|
|
# on Windows but that is not an issue since only the sizes matter
|
|
#
|
|
|
|
# mapping from path to list of files or directories
|
|
trees: dict[Path, list[Path]] = {}
|
|
|
|
# mapping from paths to either size (for file) or -1 for directory
|
|
sizes: dict[Path, int] = {}
|
|
|
|
# first line must be a cd otherwise we have no idea where we are
|
|
assert lines[0].startswith("$ cd")
|
|
base_path = Path(lines[0].strip("$").split()[1]).resolve()
|
|
cur_path = base_path
|
|
|
|
trees[cur_path] = []
|
|
sizes[cur_path] = -1
|
|
|
|
for line in lines[1:]:
|
|
# command
|
|
if line.startswith("$"):
|
|
parts = line.strip("$").strip().split()
|
|
command = parts[0]
|
|
|
|
if command == "cd":
|
|
cur_path = cur_path.joinpath(parts[1]).resolve()
|
|
|
|
# just initialize the lis of files if not already done
|
|
if cur_path not in trees:
|
|
trees[cur_path] = []
|
|
else:
|
|
# nothing to do here
|
|
pass
|
|
|
|
# fill the current path
|
|
else:
|
|
parts = line.split()
|
|
name: str = parts[1]
|
|
if line.startswith("dir"):
|
|
size = -1
|
|
else:
|
|
size = int(parts[0])
|
|
|
|
path = cur_path.joinpath(name)
|
|
trees[cur_path].append(path)
|
|
sizes[path] = size
|
|
|
|
|
|
def compute_size(path: Path) -> int:
|
|
size = sizes[path]
|
|
|
|
if size >= 0:
|
|
return size
|
|
|
|
return sum(compute_size(sub) for sub in trees[path])
|
|
|
|
|
|
acc_sizes = {path: compute_size(path) for path in trees}
|
|
|
|
# part 1
|
|
answer_1 = sum(size for size in acc_sizes.values() if size <= 100_000)
|
|
print(f"answer 1 is {answer_1}")
|
|
|
|
# part 2
|
|
total_space = 70_000_000
|
|
update_space = 30_000_000
|
|
free_space = total_space - acc_sizes[base_path]
|
|
|
|
to_free_space = update_space - free_space
|
|
|
|
answer_2 = min(size for size in acc_sizes.values() if size >= to_free_space)
|
|
print(f"answer 2 is {answer_2}")
|