This year I will be using Go once again, but in an effort to do something
different I will be using GitHub codespaces
in order to see how well it works for someone who likes to work in the command
line.
It seems like cloud-hosted development environments are becoming more common, so
I look forward to seeing how this experiment pans out.
-
Day 1: Calorie Counting - part 1, part 2
Codespaces did have a bit of a delay over ssh, though that was fairly manageable.
When saving the file the first time it took the linter some time to get going
and also it appears that codespaces does not have goimports
installed by
default, so I had to look up the standard library imports rather than rely on
the go tooling. It's all the little things that make a development environment
work.
-
Day 2: Rock Paper Scissors - part 1, part 2
I added goimports
to my environment and things ran fairly smoothly. The delay
is still just enough to be slightly annoying.
-
Day 3: Rucksack Reorganization - part 1, part 2
Bit arithmetic makes an appearance!
-
Day 4: Camp Cleanup - part 1, part 2
-
Day 5: Supply Stacks - part 1, part 2
I decided to stop using codespaces. It was fine, but the small amount of delay
over ssh was noticeable and unnecessary considering I am at my computer.
-
Day 6: Tuning Trouble - part 1, part 2
One thing python has which Go does not have in its standard library are tools
to find combinations and permutations of values from a list. Luckily I wrote
some for an earlier advent of code. I separated them into a separate library
at github.com/devries/combs.
-
Day 7: No Space Left On Device - part 1, part 2
A little tree work.
-
Day 8: Treetop Tree House - part 1, part 2
And now for actual trees. I always have a little trouble when I am trying to
measure that a condition does not occur in any of N possibilities.
-
Day 9: Rope Bridge - part 1, part 2
Fairly straightforward, but I like moving around maps.
-
Day 10: Cathode-Ray Tube - part 1, part 2
This one seemed pretty easy. I was expecting repeating the cycles for some large
number of times in part 2, but instead I got to take advantage of my AoC OCR
utility.
-
Day 11: Monkey in the Middle - part 1, part 2
I naively decided to try using the big integer library before just running a
modulo least common multiple on each worry operation. A little bit of a
detour for part 2 it turns out. Also, took me a while to parse.
-
Day 12: Hill Climbing Algorithm - part 1, part 2
A nice little reversal (literally) at the end where you have to find the starting
point with the shortest path to the end. Turns out it is easy to just start at
the end and do a breadth first search until you find the first location with
altitude 'a'.
-
Day 13: Distress Signal - part 1, part 2
I had a few bugs in the packet parser hitting a comma when I expected a left bracket
or an integer, but eventually I found the issue. After that the comparisons were
fairly easy. I completed this in a similar was as I did the Snail math problem last
year, with an interface type that could hold an integer to a list of those interfaces.
-
Day 14: Regolith Reservoir - part 1, part 2
I read the problem and thought this was going to be one of the problems where
efficiency would be an issue, but it turned out to be straightforward. Unfortunately
my flow was interrupted by a meeting between parts 1 and 2.
-
Day 15: Beacon Exclusion Zone - part 1, part 2
Not a lot to say about this problem. I should make my utils.Point methods generic
so they work on int64, but it was faster just to define int64 structs for points
and for ranges. This time my overlap function was simpler than the last time we
did a problem like this.
-
Day 16: Proboscidea Volcanium - part 1, part 2
To solve this I calculated the distances between any two valves in seconds
elapsed and restricted myself to traveling only to valves that had a flow >
0. For the first part I essentially found the distances between all valves
and then recursively did a depth first search through all possible paths that
could be done within the time limit. For part 2, initially I split the valves between the
two players and found all combinations of valves each player could have. I then
restricted each player's parameter space to their assigned valves.
Iterating through all the possibilities, even with memoization, took around
a minute, and that solution is in slow part 2, but after
that I went looking for hints and found that you could essentially keep a combined
list of all the valves and just run player 1, reset the clock, and run player 2. Reducing
the state to time elapsed, position, player (I used "A" or "B"), and open valves
reduced the run time to a few seconds. This was a very interesting problem.
-
Day 17: Pyroclastic Flow - part 1, part 2
This problem is notable because the power went out in my house and has been
out for about 36 hours now. I finally evacuated to my in-laws house and brought
my laptop to do the problem. It's basically tetris without rotations, and for
the second part you have to find a repeating cycle of pieces and motions with
the same starting grid pattern. I encoded each row of the grid as a uint8 and
then hashed that array to find a grid value I could use as a key in a go map.
-
Day 18: Boiling Boulders - part 1, part 2
I ended up filling the grid with water blocks to see where it could get. Then
I counted the number of water blocks adjacent to each rock block.
-
Day 19: Not Enough Minerals - part 1, part 2
This was very unpleasant for me. For a while I thought I had a few "off by one"
errors, but it turns out it was just misreading the problem. By then I had started
on a new approach using a BFS. It took a lot of trial and error to figure out
how to cull the queue adequately and even now it's not great.
-
Day 20: Grove Positioning System - part 1, part 2
After yesterday's doozy of a problem, at least today was nice and simple.
-
Day 21: Monkey Math - part 1, part 2
The first part of this problem was nice and simple. I put everything in RPN
and completed the calculation using a stack. The next part broke my brain. I
just wasn't getting what my errors were, and so I decided to go to sleep. The
next morning I remembered how subtraction and division worked.
-
Day 22: Monkey Map - part 1, part 2
I spent too long building a general algorithm for working out how to navigate
the cube. I think it works in many cases, but I found one configuration which
doesn't work. What I did was find the points outside the map that were touching
two sides of the map. I then walked along the edge of each map in each direction
and set up points to warp from one edge to another. It seems like if only
one runner has to make a 90 degree turn, then the edges will still touch, but
if both do, then you stop.
-
Day 23: Unstable Diffusion - part 1, part 2
I love these cellular automaton problems. I created a hash map with the elf's
current position as a key and previous position as a value. If there were collision
I would move each elf back to its previous position. And to check if any
elves moved I just had to wait until every key equaled its value.
-
Day 24: Blizzard Basin - part 1, part 2
This is a relatively straightforward BFS search with a map that changes each step.
The total number of map configurations is the LCM of the map width and height, which
for my case was 600 states which I precalculated. The tough part for me was finding
the set of states I had already seen during the search. I didn't take the map
configuration into account initially, which did not allow me to return to any
point or remain in a point. Once I cleared that up, the problem was pretty
quick.
-
Day 25: Full of Hot Air - part 1
Well, that's a weird number system.