Skip to Content

Advent of Code 2019 - Day 21, in Kotlin

Kotlin solutions to parts 1 and 2 of Advent of Code 2019, Day 21: 'Springdroid Adventure'

Posted on

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

  1. Index of All Solutions - All posts and solutions for 2019, in Kotlin.
  2. My Github repo - Solutions and tests for each day.
  3. Solution - Full code for day 21
  4. Advent of Code - Come join in and do these challenges yourself!