mirror of
https://github.com/thib8956/advent-of-code.git
synced 2026-06-15 13:38:15 +00:00
2022 day 7 part 1
This commit is contained in:
@@ -0,0 +1,86 @@
|
||||
#!/usr/bin/env python3
|
||||
import fileinput
|
||||
from collections import defaultdict
|
||||
|
||||
|
||||
class Peekable:
|
||||
def __init__(self, lines):
|
||||
self.lines = lines
|
||||
self.pos = 0
|
||||
|
||||
def peek(self):
|
||||
if self.pos < len(self.lines):
|
||||
return self.lines[self.pos]
|
||||
return None
|
||||
|
||||
def next(self):
|
||||
self.pos += 1
|
||||
return self.lines[self.pos - 1]
|
||||
|
||||
|
||||
def parse_tree(inp):
|
||||
"Parse input to adjacency list of files and directories"
|
||||
path = []
|
||||
adj = defaultdict(list)
|
||||
cmds = Peekable(inp)
|
||||
while cmds.pos < len(inp):
|
||||
line = cmds.next()
|
||||
if line.startswith("$ cd"):
|
||||
arg = line.removeprefix("$ cd ")
|
||||
if arg == "/":
|
||||
path = []
|
||||
elif arg == ".." and path:
|
||||
path.pop()
|
||||
else:
|
||||
path.append(arg)
|
||||
elif line.startswith("$ ls"):
|
||||
while (line := cmds.peek()) and not line.startswith("$"):
|
||||
line = cmds.next()
|
||||
if line.startswith("dir"):
|
||||
name = line.removeprefix("dir ")
|
||||
adj[tuple(path)].append(name)
|
||||
else:
|
||||
size, name = line.split()
|
||||
adj[tuple(path)].append((name, size))
|
||||
return adj
|
||||
|
||||
|
||||
def main(inp):
|
||||
adj = parse_tree(inp)
|
||||
# DFS the tree to calculate size of each directory
|
||||
stack = [((), adj[()])]
|
||||
visited = {()}
|
||||
sizes = defaultdict(int)
|
||||
dirs = set()
|
||||
while stack:
|
||||
path, children = stack.pop()
|
||||
for child in children:
|
||||
if isinstance(child, tuple): # file
|
||||
name, size = child
|
||||
sizes[path] += int(size)
|
||||
print(f"file {name} {size}")
|
||||
else: # dir
|
||||
child_path = (*path, child)
|
||||
print(f"dir {child_path}")
|
||||
if child_path not in visited:
|
||||
visited.add(child_path)
|
||||
stack.append((child_path, adj[child_path]))
|
||||
dirs.add(child_path)
|
||||
|
||||
# Add up sizes of subdirectories to parent directories
|
||||
for path in sorted(dirs, key=len, reverse=True):
|
||||
if path: # not root
|
||||
parent = path[:-1]
|
||||
sizes[parent] += sizes[path]
|
||||
|
||||
total = 0
|
||||
for size in sizes.values():
|
||||
if size <= 100000:
|
||||
total += size
|
||||
print(total)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
with fileinput.input() as f:
|
||||
lines = [x.rstrip() for x in f]
|
||||
main(lines)
|
||||
Reference in New Issue
Block a user