advent-of-code/2021-python/solutions/day_12.py
Anders Ytterström c0d352cdf1 Solve 2021:12 "Passage Pathing"
I struggled a lot with the direction, but realised way too much later
that the mappings are bidirectional.

Part 2 was exceptionally hard, but I realised early that the order did
not matter and that a simple boolean lock was all that was needed. The
challenge was to know when to watch for duplicates.

The seen was initially a set, but since new sets must be sent instead of
references, a list is used instead to be able to use the seen + [] hack.
2021-12-12 14:39:11 +01:00

54 lines
1.5 KiB
Python

from solutions import BaseSolution
from collections import defaultdict, deque, Counter
class Solution(BaseSolution):
input_file = "12.txt"
def __str__(self):
return "Day 12: Passage Pathing"
def parse_input(self, data):
return [l.split("-") for l in data.split()]
def solve(self, puzzle_input):
return self._solve(puzzle_input, lambda seen: True)
def solve_again(self, puzzle_input):
return self._solve(
puzzle_input,
lambda seen: any(
[
k.islower() and k != "start" and v > 1
for k, v in Counter(seen).items()
]
),
)
def _solve(self, puzzle_input, isdup):
ft = defaultdict(lambda: [])
for f, t in puzzle_input:
ft[f].append(t)
for f, t in puzzle_input:
ft[t].append(f)
queue = deque([("start", list(), False)])
s2e = 0
while queue:
pos, seen, dup = queue.pop()
seen.append(pos)
dup = isdup(seen)
for t in ft[pos]:
if t == "end":
s2e += 1
continue
elif t == "start":
continue
elif dup and t.islower() and t in seen:
continue
queue.append((t, seen + [], dup))
return s2e
if __name__ == "__main__":
solution = Solution()
solution.show_results()