2
votes
Day 11: Reactor
Today's problem description: https://adventofcode.com/2025/day/11
Please post your solutions in your own top-level comment. Here's a template you can copy-paste into your comment to format it nicely, with the code collapsed by default inside an expandable section with syntax highlighting (you can replace python with any of the "short names" listed in this page of supported languages):
<details>
<summary>Part 1</summary>
```python
Your code here.
```
</details>
Glad to have an easy day for a change! Just a simple recursive search with memoization (not needed for part 1, but it doesn't hurt). Part 2 is just the product of the solutions to three separate problems solved the same way as part 1. Would've finished this quicker if I hadn't wasted time writing a naive BFS solution that would take forever to finish executing, but oh well. I wonder what tomorrow will be like... this feels a bit like the calm before the storm.
Solution (Lily)
Computing the number of paths in a directed acyclic graph is a classical DP problem. I used the direct approach of visiting nodes in a lexicographical order, each time updating the value for its children. The lexicographical order ensures that when visiting a node, I've already visited all its parents and its value is not going to change.
For path 1, the value of each node is just the sum of its parents, initializing the starting node with 1.
For part 2, I used exactly the same approach, except that I'm using 4 values for each node, each corresponding to one type of path: paths going through neither dac nor fft, paths going through dac but not fft, paths going through fft but not dac, and paths going through both. For most nodes, their counters are directly propagated to their children. For dac and fft nodes, the none counter gets propagated to the dac and fft counters respectively and the fft and dac counters respectively get propagated to the both counter.
Boths are O(n) with n the number of nodes in the graph, so it's super quick to compute, even when using strings as key/values for the graph (and doing a ton of copies): 60μs for part 1 and 420μs for part 2.
Solution (Rust)
Much easier today. Of course, that didn't stop me from making the same mistakes as yesterday.
Copied my BFS code (that was several orders of magnitude too inefficient for yesterday's problem) from yesterday to solve part 1. Why didn't I reuse the DFS (that also was too inefficient for yesterday's problem)? Because the BFS code was prettier.
Get to Part 2 and realized I should have just started with DFS. Oh well. Easy enough to just rewrite a DFS. Luckily, DFS is actually the right tool for this job, and this worked as expected. My original plan was to use a "visited" check for visiting the fft and dac nodes, but that turned out to make caching much more complicated than I wanted.
Part 1&2 [Python]