Note: I accidentally blew away all of the content of this post, so forgive me if it's suddenly much different than it used to be.
On Day 16, we've got some example inputs and outputs to machine instructions in our time machine and we need to figure out which opcodes do which things.
There were a few challenges similar to this in years past. Let's see how everybody likes this one.
Top comments (6)
Machine simulations have come up before in Advent of Code and are fun to implement. This one is an interesting twist. As I read the description I thought we were going to have to decipher the opcodes, but fortunately part 1 is a bit simpler than that.
Parsing
Complex text structure again. You know what that means! A data model and a JParsec parser.
Machine simulation
At first I wrote all the instructions out as Kotlin functions but then decided it might be better to encode them as lambdas along with additional information such as the name. I wrote them as destructive in-place operations on a
Registers
since I have the feeling we're going to have to run the program at some point!Part 1
Since we need to run different instructions over the same input data we really need non-destructive versions of these operations. That's possible with a simple wrapper.
Checking the number of operations which match a sample is easy;
And checking the number of samples which pass this test is similar:
Part 2
Now we really have to map opcodes to instructions! This is an extension of the part 1 puzzle where the samples are matches to opcodes. We have to deduce the unique mapping of opcodes to instructions however. My algorithm for this was:
In Kotlin:
Running the program is a simple fold over the registers. Turns out I didn't need my in-place destructive operations after all, so there's a possible refactor there.
Full code on github
Fortunately, much easier than yesterday, it would have ruined my Advent otherwise.
I started implementing the dispatch table for the opcodes like this
but it was a lot of repetitive typing, so I let Perl generate the code for me from simpler strings.
The rest of part 1 was easy: for each input case, just count how many opcodes modify all the registers in the given way and keep a count of the cases where there were at least 3 such opcodes.
For part 2, I collected all the guesses for each instruction number, and kept removing those that only had one solution until I knew all of them. Then I just translated each instruction number to the opcode and ran it.
For this challenge I spent most of the time parsing input (those pesky line breaks).
After I meticulously recreated table with opcodes, solution itself was straight forward.
Part 1 - test each command, add to counter if success, add to bigger counter if more than three successes.
Part 2 - test each command to get a table with all possible opcodes, then find opcode(s) that have only one option, remove that opcode from the table. Repeat until the table is empty.
readFile.php
I agree with the main sentiment here, that there didn't seem to be a whole lot to this one. Lots of typing, but not too much thinking. I didn't like my initial code very much, though, I so I refactored some. I'm leaving all of the operations out
addr, addi, etc.
because they take up a lot of space and are all basically the same. Check them out in the git repo.Of course we have to see some of those ;)
I like these kind of problems very much - they are especially easy to do in languages with coproduct-type support.
Compared to yesterday this one was easier - I hope we'll come back to this again.
JavaScript solution
I'm gonna omit reader.js which is the same as the other solutions and jump to the point:
16-common.js
16a.js
16b.js