Hello everyone, it’s time for your Advent of Code 2021 Day 6 log. I feel like today the problem catfished me into thinking I would have an easy one. Deep down I knew that today’s challenge would throw a curveball at me. It’s my fourth year doing these and somehow I got got like a noob. The fact that I woke up late, meaning 7.30am just gave me time to solve it before work. That’s why I’ve only finished my workout session now. 7.09 pm in London. Now I can finally write that entry and push the code to the repo. At long last, let’s do this.
Today we had a game of life kind of deal focusing on lanternfishes. Basically we had an internal clock property for each fish which would change each cycle or day. This internal clock would help figuring when a fish would give life to another. The goal is simple, count how many fishes we get after X days. The logical thing if you’re dealing with a small sample of data is creating a Lanternfish entity within a Lanternfish pool. This is what I implemented at first, even though I could feel the second part would not be that easy.
I implemented that first attempt, brute model in about ten minutes. Naturally, the test using the sample data went green instantly and I got the first start of the day instantly. Nice and sweet. Maybe a little too nice, and too sweet. The second that first star appeared, I knew I would run in some sort of heap exception when trying to run the input for part two. And there it was, increase the number of days from 80 to 256. While I knew this would fail, I figured I would roll the dice. As the result failed to appear right away I knew. About twenty or thirty seconds later, I got a nice Java heap space error. Same thing on the unit test.
From there I was stumped. I figured the key might be one of these mathematical solutions but I couldn’t see what. Then after a poking a clever brain for a couple minutes, I realised that I wasn’t thinking with the right paradigm. The internal clock is the key. The only special thing about fishes is their internal clock value. There is no other information about them. They’re basically numbers. Numbers that can go into buckets. Buckets that I would determine using the clock value. When a fish clock decreases or resets I just move them to the right bucket. Sounds too simple to be correct so I start coding again.
I only had to change some of my lanternfish pool to make it work. While it did take some time to fully wrap my head around what needed to be done it eventually felt clear as day. After typing away for a few minutes my new code passed the part one test but not part two. The value felt way too small. Then I realised my mistake. We’re talking exponential growth and there’s no way an integer can contain an exponential value of order 256. None.
This was some sort of overflow error so I changed my containers to use BigInteger instead. Now all my tests failed. I went around and modeled each day with the sample data manually with paper and pen. I could not figure how my code would not yield the right result for part two, nor part one. It worked a second ago just before I switched from integer to BigInteger.
I went around my code for a good dozen of minutes when I saw it. My fish counting method was summing stream of integers which doesn’t work for BigInteger. As a result when switching to the BigInteger implementation, I used a good old for loop. Loop that I copied from my ticking method. Loop starting at 1 instead of 0. Stupid me. I changed the loop to start from 0 and all tests passed. The input run landed me my twelth star of the season. The this will be a good day. Spoiler alert from future JD: it was.