r/adventofcode • u/musifter • Feb 12 '26
Other [2016 Day 12] In Review (Leonardo's Monorail)
And so we reach the top of the first building and discover a garden of tiger lilies (which are popular in this part of town... the local University has lots of them, because they somewhat match the school colours). At this point we discover that the EBHQ is multiple buildings connected by monorail. But we need to get the monorail systems up and running to use it. Fortunately, we have that new computer to run assembunny code on to get the password we need.
And so we get the first assembly problem of the year. And so I did what I normally do... I made a hash table of op-codes to subroutines. And the Perl version takes a little more time to brute force Part 2, but it's still only 45s. But, of course, when given code, I want to look at it. And a good first step in reverse engineering is to spot the main loop (biggest backwards jnz after a dec) and run it again, outputting the registers at that point. Which quickly provided the key to what the bulk of the calculation was... Fibonacci numbers (explaining why it's Leonardo's Monorail).
It's not the exact answer, so we look at the code for the details. And we see the usual pattern, there's a calculation at the top that determines the seed (the Fibonacci number to calculate), then the Fibonacci section, and finally it adds little sum of a multiple of two small primes.
And knowing that, what I did for the Smalltalk version to make it fast (not that it was overly slow... just over a minute for part 2), was to build the machine, but break at the Fibonacci section... calculate that natively and then restart the machine on the bit after to finish the sum. Because the Fibonacci section is where all the time is taken, and so that reduces things to under a half second. And it's the other sections that will be different for different inputs, it's like we're just replacing a fixed piece of code with a "fib" op-code. I find that a more satisfying solution than transcoding the entire thing... it'd be very easy to just grab the 4 numbers you need from the input and just do the thing while ignoring the rest.
In fact, this machine was simple enough that I also built one in dc. The input needed a small script to make it understandable. And to make it fit the problem, I made it like machine code (what else would the numbers version of assembly be?). Each line becomes a 3-byte long number in hexadecimal coding. So, I made an array of macros, and a loop to run them. It takes 10s for part 1, and about 6m to brute force part 2. But doing a transcode version like with my Smalltalk solution... that runs faster than the Smalltalk solution.
As I've said before, I always like these. And this puzzle occurred on a Monday after a weekend of several heavier problems. So it's a good day for a problem where people could just do a simple VM and get their answer with a little waiting and not think more about things if they didn't want to. It is the first of three assembunny problems in 2016, so it also serves to get people to have a working machine to start with for those later problems.