Hello, there and welcome to my Advent of Code 2020 Day 20 cruise log. We are on Monday, December 22nd so you know that I failed to complete the challenge on time. Technically I completed it 5 minutes before Day 21 started but I’m not sure how. Since I hate sharing code I don’t fully understand, I decided to do a post-mortem instead to try and figure what went wrong. Even though it ended up working I’d rather fully capture the solution process so I decided to tackle Day 21 first and then re-attempt Day 20 from scratch. First, let’s start with the beginning.
December 20th, 5 am, sitting at the desk ready to take on a new challenge. That’s how this story begins. Well, this post-mortem. Little did I know, I was about to commit the biggest crime in software less than 24 hours later. Unbeknownst to me, this day’s log would not see the light of day before another day later.
Let’s keep good habits and start with the lore. Even though we broke them by getting this log out only now we should still keep some structure. As our train leaves the jungle, we get some communication from the Christmas elves. They need our help, as usual, to now process the satellite messages we help decipher on day 19. The monster-related ones. After decoding the messages then, our hero realises that these represent image information. Information that will reveal to us where the sea monsters are once we rearrange them.
The first part consists of making sure we have the right cameras at each angle. There are two ways of solving that. Originally, I created a grid detecting adjacent cameras and plucking them together. From there I would return the product of each corner camera id. Even though it took me a few hours to implement I got my first star of the day. Fate or fatigue would decide this would be my last that day. Indeed, hours kept passing and I would remain stuck. The cameras have the right positioning according to the subject. Roughly, if you flip it a bit they do. This would have been a hint if I paid more attention to the part about flipping and rotating cameras and tiles. That’s the first thing that went wrong. After sundown, I admit defeat and call it a day.
The next morning, it is about 3.50 am, yes I didn’t sleep well that night, go figure. While in bed, I worry about getting stuck the same way on day 21 which is about an hour away. Maybe it is the lack of sleep that got me to act irrational, maybe it is due to slipping down the company leaderboard. No matter the cause, this is the moment decide to commit the highest crime a developer can do. If my brain would not get me this 40th star then force would, brute-force.
And there I go, hacking away, writing code of virtually infinite time and space complexity, I lost track. Venturing deep in the zone but not the usual with Celine Dion in the background. This one is dark and moist with Slipknot’s Psychosocial raging in my ears.
Butchering away for almost an hour, eventually, a disfigured creature emerges. My very own Frankenstein monster if you could describe code as such. I execute it against the example, while it took a few minutes to run it did work. The test is green, the time to put my coder honour down for a moment, I launch the monster at my input. They battle for a few minutes but the monster emerges with a bloody carcass. The answer to my prayers laying bare in front of my eyes. I submit it to the gods and they reward me with a blood-stained star. Full of shame, I refuse to share this “accomplishment” on Twitter.
I barely have the time to recover from the carnage that day 21 begins. I will not expand on this but there is already a daily log for it so feel free to have a read. After doing fairly quick work of the day 21 challenge, I vow to come back and right my wrongs. Redo day 20, but do it right this time. No summoning demons, no lamb sacrifices, only pure and honest to God code. This is why you only read all of this now. Why share the monster story? Because now that I publish it, my conscience is clean of that atrocity.
Restarting day 20 from scratch, knowing the dark place where it took me is a big risk. I can undermine my confidence for good if I fail to do it within a few hours. I need to go through this, so that I can truly learn from this experience, know what went wrong and avoid repeating it. This is good. Not just good for a professional developer but good blogging material.
I will do things differently now that the leaderboard pressure is off my shoulders and use some pen and paper first. Actually, that doesn’t make much sense to say that since this morning, I spent more than half an hour working the solution with pen and paper before writing any line of code. This can only help me, right? I’ll do that anyway. Just so you know, I’m using the present term because I’m redoing day 20 as I write this part. This will be the freshest log you will ever read here. I guess that is a thing I can do without leaderboard pressure.
I will not start fully from scratch though, I will keep the bits that work well like the parsing and loading of cameras. The nightmare began with the rearranging of these, not before. I have free time but I shall not waste it rewriting bases. Mostly, what I need to rewrite is the arranging of the cameras to be in the right position. No more, no less. Then I can find peace and relax until day 22 comes.
After getting rid of all the noise in my original code, I started pondering on what should make the first part work. Originally, I would create all possible combinations of each star and have a map to keep track of what I had put in the result box. The problem with that approach is that I effectively lost which orientation is the right one. From there, we change approach and focus on the edges this time. If an edge is shared with at least one other camera then it cannot be part of a corner. However, if an edge isn’t shared with another camera then we’re onto something. Once we get two of these for a camera, then that camera is an angle one. So I start writing this code to redo part one.
After implementing this new code, I run my existing part one test, it fails. I thought I went too fast to be correct. So I went back over the problem and realised that I forgot to consider the flipping flipping. I need to add that to the possible edges so I would have four unique edges which are twice the corner ones as we can flip them. Shortly after that realisation, I put the adjustment in and the test went back to green. Executing against my input gave me my star-capturing result so I could move onto part two.
Things went significantly faster this time as the last with a much simpler solution with less filth in it. I am quite satisfied with how it’s going. Let’s try to keep things tidy for part two as well. I will keep relying on the edges stuff as that might just be the key to this. But first I will take a break to keep my mind fresh. Even though I always boggle people on how important they are, I fail to take them during AoC challenges. This isn’t one of these early days that I can clear in a matter of minutes anymore.
The break is nothing crazy, I went to chat with the girlfriend taking a breather from working out while refilling the water. These days we mostly talk about how much COVID sucks and how we might not get to return abroad to visit our families. After chatting I went out to throw out the recyclables to eventually return to my desk.
Now back from the break, it seems that trying to build the camera grid during part one is a wise choice. Doing that could have led me right into a fast second star if I didn’t fail to build the arrangement part. Now, with that newfound edges focus, I feel like I can do it in a swifter fashion. If only I had that insight yesterday at the same time. Well, I wouldn’t write a post mortem now and this is good blogging content. You’re welcome!
After about forty minutes of coding, I get stuck again. The code to detect my top left corner doesn’t seem to behave as it should. The dread of getting stuck there for ages once more crept in. However, unlike yesterday, I found an issue with the combinations. I took all of them in considerations. I gambled that maybe I can ignore the flipped versions of my top-left corner and get away with it. Now it seems to work and I can write the logic to fill the cameras grid. I get stuck once more. Apparently, the placing is okay but something is wrong, the algorithm skips the last row of the example.
After putting a few prints here and there, I realise what is wrong. After refactoring my method to create tiles combinations, I forgot to add back the flipping permutations. Now the code picks up the final row and can finally return to the image processing. I kept my original image creating method so I execute it and can see that the tiles have proper alignment. You have to put your head sideways and imagine a flipping to see it but it is there.
Now that we have the image, we need to find the orientation where we can find monsters. I kept my code doing that as well since this is code I found no issue with. Really, the placing and orientation of tiles caused all the pain. No brute-force to find the second-star answer today. Not again. We’re doing it right this time. But first, let’s have lunch.
Obviously, things didn’t go according to plan. It seems that the last line of cameras isn’t put together correctly. Putting my head sideways isn’t the greatest debugging tool I guess. Looks like my camera arrangement still has issues. I’m slowly realising that I still need to fix the camera’s orientation even though I was certain I already handled that bit.
In case my arrangement didn’t place the tiles correctly, I modified my part one code to use it to calculate the corners are there. The test is still green. The cameras may have the right positions but maybe the tiles don’t. Displaying the cameras positions confirms this. While I have the same disposition as the example, debug shows a vertical and horizontal flip on the grid.
From there, I spent some time and after realising I will need to debug and potentially refactor my arranging method once more I called it a day. Two more hours burnt at the altar of that day 20.
Now we’re on the 22nd, I did pretty quick work of day 22. I got my 43rd and 44th stars in under two hours. After completing yet another day making the trickery of day 20 feel like a mental block, I took a break. One would say I took that time to put the break in breakfast. Then, I took some time to chat and got back on this post-mortem post. Looks like sleeping pays dividends as I spot within half-an-hour what is wrong with my arranging method. As it turns out, cameras don’t all have the right orientation. Even though they are in the right position relative to one another, it seems to be a complete accident once more.
Weirdly enough, I got back to the same result as the first time, except I did it way faster. Also, I still won’t surrender to using brute-force code. Otherwise, what’s the point of this post-mortem. For the first time in ever, I realise there is a debugging option for Golang in VSCode. Can’t believe I didn’t see this earlier. I put some breakpoints in and fairly quickly find where things go south. I don’t update the top edge. While this work to detect the first row of cameras, it prevents you from matching any other camera afterwards. Upon this discovery, I apply a fix with some level of trial and error, but eventually, I fixed it.
Now replacing that ghoulish creature I summoned yesterday morning there is a beautiful nymph standing in front of me. Ready to go, detect and slay dragons. As she has her way with my input, she brings me a beautiful, polished star. A star shining like a thousand suns, I wish I met her two days ago, she is magnificent. That one I can show to all the devs out there. That one belongs to my repository and shall lay there between 19 and 21. No more brute-force, only style and grace shaped as code.
Thank you for reading my Advent of Code 2020 Day 20 cruise log, I will see you tomorrow, maybe. In the meantime, you can check out my Go Cloud series about building and deploying a Golang app to AWS. Also, I will push my code on Github at CodingNagger/advent-of-code-2020. Feel free to check it out but not before you’ve done the challenge yourself. Bye!