Advent of Code 2021, Day 1
Advent of Code is here again, and I’ve been looking forward to this! I’ve been doing AoC since 2019, so this will technically be my third year, though I’ve done some older puzzles in the meantime. My work from past years is available on my public git repository, and this year’s will be too.
I started out with 2019 in Python, because Python was safe and familiar, while AoC was new and a little intimidating. It went pretty well until I ran heads-first into day 19 and stalled for a bit, which is a pattern that tends to repeat. AoC very definitely gets harder as the month goes on, and the last week tends to be particularly challenging. I’m not going to berate myself if the same happens this year, because ultimately it’s all just a bit of fun.
Later on, in 2020, I did Advent of Code 2015, again in Python, and completed it. That gave me the confidence to go back and finish 2019, and from there, I decided to use AoC 2016 to teach myself Rust. I once again got as far as day 19 and stalled; I still haven’t gone back and finished it.
Then AoC 2020 rolled around. I set myself a challenge and decided to do the whole thing in Haskell. I’d never used Haskell before. It was kind of fun, but more work than I could keep up with given stuff going on at my job at the time.
My approach this year
If you’ve been following my blog or fedi account, you know that the last few months have been pretty wild for me, having to deal with a double-whammy of plurality and finding out I have EDS, so I’m not setting such lofty goals this year. No, this year, I’m going back to my roots and doing it in Java.
Why Java? Well, Java was my primary development language at university, and has remained so for most of my professional life. Due to some Technology Shenanigans, however, I haven’t had much chance to use it this year at work. It’s safe, it’s comfortable, and I miss it.
This opens up some possibilities I haven’t had when learning a new language or hacking away in Python. I can use every trick, both clever and dirty, I’ve learned from working with Java for the last eighteen years. The order of the day is going to be Test Driven Development.
The author of AoC is kind enough to provide examples for both parts of each puzzle, consisting of some simple test data, the solution, and a brief explanation of how you get from A to B without actually spoiling the puzzle. It’s very nice for understanding the puzzles themselves, but it also gives me an opportunity to set up tests for my solutions before I even write them. This lets me hack away at the solution, re-run my tests, and when they pass, it’s (probably) right.
How am I going to run the solutions themselves, though? Well, that’s still an open question. There are lots of ways to run Java. To start with, given my very limited energy, I’m going to do it in the simplest way possible, a command-line program that just loads up the input file and spits out the solution to the console. Yes, my friends, it’s time for good old public static void main(String[] args)
.
Day 1
So, day 1. It’s always a nice, simple one to ease you in, and this year’s is no different.
Spoilers for AoC 2021 day 1 follow.
Looks like we’re doing a voyage to the bottom of the sea this year! I definitely like this premise better than last year’s vacation-themed one. I’m not sure anything is going to top 2019’s interplanetary adventure for me, but this one has real potential.
The puzzle itself is pretty generic, like I’d expect for day 1. Go through a list of numbers and count how many numbers are bigger than the one immediately before it. This won’t take long.
First thing, I get my development environment set up, drop JUnit (the test framework I’m using) into my libraries, and off I go. Step two, do the same thing I do every year, write a quick function to load the input data from the file, going for a list of strings this time. That’ll go in my new Util class.
Now I can do the TDD thing and set up my test class. I just hard-code the example test data into it, not doing anything clever there, and have it run tests against the part1
and part2
methods on my as-yet-nonexistent Day01 class.
Then I create that. Once again, keeping it simple, the main method just runs both parts and prints out the results. As an afterthought, I have this implement a generic Solution interface with the part1
and part2
methods defined in case I want to do something clever with it later.
And now, finally, we get into the substance of the puzzle itself. Part 1 is really straightforward: interpret the input as a list of numbers (parseInput
method, check!), iterate through it, and count each time it’s higher than the last one. Six lines, not counting the file parser.
Part 2! This one wants to smooth out noise in the input data by comparing a sliding window of three values. A little trickier, but not by much. And ooh, the example shows what each of the group values should be! New test method!
Once you’ve got those three-value groups and summed them, you’re just checking for increases again. So, pull my increase-counter out to a common method, have both parts call that, part 1 with the raw number list, part 2 with the group sums. Done!
And now, with my own input data, the answers are 1665 and 1702 respectively. If you haven’t done AoC before, you should know that these answers won’t work for you, it gives you your own input data with its own set of answers.
That was fun! Took less time to do than this blog post took to write. Hopefully I’ll have the energy to keep up with this as it gets harder, but I’m not going to beat myself up about it if I have to quit.