Advent of Code 2019 - Day 21, in Kotlin
Kotlin solutions to parts 1 and 2 of Advent of Code 2019, Day 21: 'Springdroid Adventure'
Today we’ll write some assembler code an feed it to our IntCode
computer to see if we can make a springy robot do our bidding!
If you’d rather just view code, the GitHub Repository is here .
Problem Input
We’ll parse our input the same way we do for other IntCode
problems:
class Day21(input: String) {
private val program: MutableMap<Long, Long> = input
.split(",")
.withIndex()
.associateTo(mutableMapOf()) { it.index.toLong() to it.value.toLong() }
}
⭐ Day 21, Part 1
The puzzle text can be found here.
I’m not a huge fan of today’s problem. It’s really brilliant work on the part of the puzzle creators, but I’m just not good at assembly and really struggled with this one. I did seek some help, and I’ll do my best to explain what we’re doing as I go.
Before we start, we’ll need a function to start our computer, write our program to it, and listen for the answer:
private fun runWithInput(input: List<String>): Int = runBlocking {
val computer = IntCodeComputerMk2(program)
val cpu = launch {
computer.runProgram()
}
input.forEach { line ->
line.forEach { c ->
computer.input.send(c.toLong())
}
computer.input.send(10)
}
cpu.join()
computer.output.receive().toInt()
}
Because we have to send in ASCII integers, we’ll call Char.toLong()
on each character of our input. Every time we’ve finished writing a row, we’ll send in a 10
, which is ASCII for carriage return. Once the computer halts, we’ll read the single output available (because we’re using a conflated channel for output, we’ll only ever see the latest value).
Now, the matter of what we want to use for input
. This is what I had trouble with, so I’ll annotate what I ended up using:
NOT A J // If there is a hole one spot away, set the jump register to TRUE
// otherwise set it to FALSE
NOT B T // If there is a hole two spots away, set the jump register to TRUE
//otherwise set it to FALSE
AND D T // Set the temporary register to TRUE if there is a hole four spots away
// Note that the temporary register is FALSE when we start
OR T J // Set the jump register to TRUE if either the jump or temporary
// registers are TRUE, otherwise FALSE
NOT C T // Set the temporary register to TRUE if there is a hole three spots away
OR T J // Set the jump register to TRUE if either the jump or temporary registers
// are TRUE, otherwise FALSE
AND D J // If there is a not hole four spots away, and the jump register is true
// set the jump register to true
WALK // Execute the program
I had a lot of help with this. We’re always scanning ahead and carrying forward our calculation on whether to put a TRUE in the jump register. Running this input into our computer as a List<String>
(one command per line) solves part 1.
⭐ Day 21, Part 2
The puzzle text can be found here.
We have what we need already, we just have a way more complicated program (which I also had a lot of help with):
NOT C J // If there is a hole three spots away, set the jump register to TRUE
// otherwise set it to FALSE
AND D J // Set the jump register to true if the jump register is TRUE and there is
// not a hole four spots away
NOT H T // Set the temporary register to true if there is a hole eight spots away
NOT T T // Invert the temporary register if it is false
OR E T // If the temporary register is true or there is a not a hole five spots away
AND T J // Set the jump register to true if it is already true and so is the temporary register
NOT A T // Set the temporary register to true if there is a hole one spot away
OR T J // Set the jump register to true if it is already true or the temporary register is true
NOT B T // Set the temporary register to true if there is a hole two spots away
NOT T T // Invert the temporary register if it is false
OR E T // Set the temporary register to true if it is already true or there is a not a hole five spots away
NOT T T // Invert the temporary register if it is false
OR T J // Set the jump register to TRUE if either the jump or temporary registers
// are TRUE, otherwise FALSE
RUN // Execute the program
Part 2 solved. I don’t really feel like I learned a ton doing this one, and it was personally somewhat frustrating. I did well in my assembly class in college (do they still teach it?) but I haven’t used it outside of Advent of Code since. :)
Further Reading
- Index of All Solutions - All posts and solutions for 2019, in Kotlin.
- My Github repo - Solutions and tests for each day.
- Solution - Full code for day 21
- Advent of Code - Come join in and do these challenges yourself!