I woke up early today, opened the day’s puzzle and saw that we’re back to the lava production facility. I knew that meant path finding and those have usually been my Achilles’ heel as recursion is a challenging one for me.
Then I continued reading and found out that we met a a reindeer wearing a hard hat which reminded me of the fantastic story about zoo animals in hats by Rhod Gilbert in Would I Lie To You and I immediately got on a better mood.
Read input
Today’s input is another grid of numbers
Each number represents a height in a topological map. Every 0
is a trailhead and every 9
is a peak.
As we construct the grid, we also keep track of all the trailheads because those are the starting points of hiking paths that we need to find.
Part 1
In the first part, we need to find out how many peaks we can reach from each trailhead. To reach a peak, we can only move in cardinal directions (up, down, left, right) and only to another location if it’s exactly one higher than where we currently are.
First, we need a way to get all the neighbouring coordinates so let’s build a helper function. The named tuples really shine here, don’t you think? It’s easy to read on a glance what’s happening.
To find all the paths, we use recursive depth-first search:
Our base case is if we’ve reached the peak in which case we return the current position (wrapped into a list since our recursive function always returns a list).
If we’re not at the peak, we go through every possible neighbour and if it’s 1 higher than where we currently are, we find all paths from there to the peaks.
We then end up with a list of peak positions.
To calculate the score, we go through every trailhead and find all the paths for every trailhead. Since we can reach the same peak position through multiple paths, we remove duplicates by converting the list
to a set
and get its length.
Part 2
In the second part, a trailhead’s rating is how many unique paths there are to peaks.
As a stroke of luck, we already calculate that in the first part. This time, we don’t remove the duplicates and we’re done.
I actually first accidentally solved the second part, then realised I need to remove duplicates. When the second part rolled in, I already had the solution ready.
I could have combined the two parts into a single function and only calculate the hikes once. But I like to keep my solutions consistent day to day for easier reading and I don’t care about the overall run time so here we go.
I was done by 8am today, including refactoring and write-up (puzzles open at 7am) so that was quite a change from the usual.