Advent of Code 2025 Day 11: Reactor
"""Advent of Code 2025: Day 11 - Reactor"""
from advent import nx, prod, cache
G = nx.read_adjlist(open("app/day11.txt", "rb"), create_using=nx.DiGraph)
@cache
def dfs(node, dst):
return 1 if node == dst else sum(dfs(n, dst) for n in G.neighbors(node))
def part1():
return dfs('you', 'out')
def part2():
return sum(
prod(dfs(src, dst) for src, dst in zip(seq, seq[1:]))
for seq in (('svr', 'fft', 'dac', 'out'), ('svr', 'dac', 'fft', 'out'))
)
assert part1() == 640
assert part2() == 367579641755680
Solution
I'm really loving Python as my relatively new primary programming language!
Today's puzzle involves depth first search and graphs. A key element today is memoization, or caching function results. Without memoization, it's extremely slow!
I used the networkx library, and
it can read graphs in adjacency list format, so getting the graph of our network is just:
Our depth first search helper function is super simple, and Python makes the memoization
trivial with a @cache decorator. We search from the node to the dst in depth first
manner - if we've reached the dst, we return 1; otherwise, we sum the results of
recursively searching each of the neighbors:
With the preliminaries in place, part 1 just searches from you to out. For part 2,
we search for 3 successive segments, and multiply each of their totals together. Our input
only has dac following fft, but I also summed fft following dac (always zero in my case)
for completeness, so it would work on any input:
def part2():
return sum(
prod(dfs(src, dst) for src, dst in zip(seq, seq[1:]))
for seq in (('svr', 'fft', 'dac', 'out'), ('svr', 'dac', 'fft', 'out'))
)
Alternate Solution
It's also possible to search from the source all the way to the destination in one shot. To do that
for part 2 we need to keep track of whether we've visited dac and fft, because a successful
path from svr to out must have visited both of them:
"""Advent of Code 2025: Day 11 - Reactor (alt version)"""
from advent import nx, cache
G = nx.read_adjlist(open("app/day11.txt", "rb"), create_using=nx.DiGraph)
@cache
def dfs(node, fft, dac):
match node:
case 'out':
return 1 if fft and dac else 0
case 'fft':
fft = True
case 'dac':
dac = True
return sum(dfs(n, fft, dac) for n in G.neighbors(node))
assert dfs('you', True, True) == 640
assert dfs('svr', False, False) == 367579641755680
