Skip to Content

Advent of Code 2019 - Day 25, in Kotlin

Kotlin solutions to parts 1 and 2 of Advent of Code 2019, Day 25: 'Cryostasis'

Posted on

We’ve reached the final day of Advent of Code 2019!

If you’d rather just view code, the GitHub Repository is here .

Problem Input

Our final IntCode problem!

private val program: MutableMap<Long, Long> = input
    .split(",")
    .withIndex()
    .associateTo(mutableMapOf()) { it.index.toLong() to it.value.toLong() }

Day 25, Part 1

The puzzle text can be found here.

Let’s talk strategy before we dive in. Today’s puzzle is a game, so we have two options:

  1. Play the game, wait for the answer, and type it in.
  2. Write some code to:
    1. Map the maze
    2. Collect all of the items that won’t kill us
    3. Try various combinations of items until we trigger a win
    4. Parse out the answer

Games were meant to be played, so we’re going to go with option 1. :)

fun playGame() = runBlocking {
    val computer = IntCodeComputerMk2(
        program = program.copyOf(),
        output = Channel(Channel.UNLIMITED)
    ).also {
        launch { it.runProgram() }
    }
    launch {
        while (!computer.output.isClosedForReceive) {
            computer.output.receive()
            while (!computer.output.isEmpty) {
                if (computer.output.isClosedForReceive) {
                    return@launch
                }
                print(computer.output.receive().toChar())
            }
            if (!computer.output.isClosedForReceive) {
                withContext(Dispatchers.Default) {
                    "${readLine()!!}\n"
                }.forEach { c -> computer.input.send(c.toLong()) }
            }
        }
    }
}

Because our IntCodeComputerMk2 uses coroutines, we’ll start our game loop using runBlocking. From there we set up our computer, remembering to give it an unlimited output buffer, and launch it in its own coroutine.

Next, we’ll launch another coroutine for our input/output loop. So long as the computer is actively working, its output channel will be open. So we’ll loop until the output channel is closed, signaling that the game has ended somehow.

First, we suspend and wait for any kind of output from the computer. In my experiments, this is usually a newline so we can discard it, using that as a signal that the computer has produced output for us. We’ll read fro the channel and print out each Long we receive, after converting it to a Char. We’ll need to check that the output loop is still open here, because if the game ends we don’t want an error on the screen.

Once we’ve read and printed all the output, the computer will wait for us to provide it some input. We do this by collecting input from the console using readLine and sending it character by character to the input channel for the computer.

Fire this up and have fun playing. I mapped my environment out using Asciiflow Infinity, which was very helpful. I had a lot of fun playing this game, it reminded me a lot of the text-based adventures I used to play and write when I was just learning to program.

I also wrote a version of this that will auto-play my specific solution, and that can be found in my GitHub.

I hope you had fun with Advent of Code 2019!

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 25
  4. Advent of Code - Come join in and do these challenges yourself!