Solve 2022 day 7 pt 1-2

Funny that I did not mention the problem with
recurring directory names in the first run of this
puzzle in Elixir, back in 2022 and bb708a5e58.

Most likely, the insight flew over my head that
time.

This time, I realized I could just add the size to
the size of each parent. I struggled to find a graph
traversal for it, until I realized I did not need
the graph.

The key rewrite was this:

    for p in path:
        fs[p] += size
    fs["/"] += size

... to this:

    p = "/"
    fs[p] += size
    for dir_name in path:
        p += f"/{dir_name}"
        fs[p] += size

This solved my issues for 3 hours by acknowledge that

- a directory name "a" can accour on multiple places,
  example: /a, /b/a, /c/a
- a directory name "a" can have a parent directory named
  "a", example: /a/b/a, /a/c/d/a

And as always, example input is the devil. Look at
the reak input as soon as possible.
This commit is contained in:
Anders Englöf Ytterström 2025-11-23 23:39:37 +01:00
parent eef1baf6b5
commit 4dfb12e246

View file

@ -0,0 +1,54 @@
from collections import defaultdict
from output import ints
def solve(data):
fs = defaultdict(int)
pwd = []
for cmd in data.splitlines():
if cmd.startswith("$ ls") or cmd.startswith("dir "):
continue
if cmd.startswith("$ cd"):
d = cmd.split()[-1]
match d:
case "/":
pwd = []
case "..":
pwd.pop()
case _:
pwd.append(d)
continue
a = ""
w = sum(ints(cmd))
# in example input, all directories have distinct names.
#
# the puzzle input have repeated directory names, e.g. both
# /d/a and /c/b/a (a subfolder named "a") exists.
#
# Furthermore, puzzle input also has cases of /a/b/a,
# e.g. a recurring across directory path.
#
# Lost several hours due to this.
fs[a] += w
for p in pwd:
a += f"/{p}"
fs[a] += w
p1 = sum(i for i in fs.values() if i <= 100_000)
free = 70_000_000 - fs[""]
needed = 30_000_000 - free
p2 = min(i for i in fs.values() if i >= needed)
return p1, p2
if __name__ == "__main__":
with open("./input/07.txt", "r") as f:
inp = f.read().strip()
p1, p2 = solve(inp)
print(p1)
print(p2)
assert p1 == 1644735
assert p2 == 1300850