DEV Community

Cover image for Advent of Code 2019 Solution Megathread - Day 19: Tractor Beam
Jon Bristow
Jon Bristow

Posted on

Advent of Code 2019 Solution Megathread - Day 19: Tractor Beam

Well, if Mark shows up, we have a way to keep him from tearing us apart now! It's an IntCode program!

Day 19 - The Problem

After escaping from Triton, we took the tractor beam with us because it probably is going to help us tow Santa back in.

First, lets test the pull on this baby. Part 1 is to find the number of squares affected by the tractor beam. We can do this by sending drones out with our IntCode interpreter.

Now that we have the shape of the beam, lets try to find the closest we need to be to grab a sleigh sized object. Sleighs are probably 100x100, so in Part 2 we need to find the coordinates of the first 100*100 box covered by our beam.

Ongoing Meta

Dev.to List of Leaderboards

If you were part of Ryan Palo's leaderboard last year, you're still a member of that!

If you want me to add your leaderboard code to this page, reply to one of these posts and/or send me a DM containing your code and any theming or notes you’d like me to add. (You can find your private leaderboard code on your "Private Leaderboard" page.)

I'll edit in any leaderboards that people want to post, along with any description for the kinds of people you want to have on it. (My leaderboard is being used as my office's leaderboard.) And if I get something wrong, please call me out or message me and I’ll fix it ASAP.

There's no limit to the number of leaderboards you can join, so there's no problem belonging to a "Beginner" and a language specific one if you want.

Top comments (1)

Collapse
 
jbristow profile image
Jon Bristow

Kotlin solution! I had a lot of issues figuring out that I was off by one!

import arrow.core.Either
import arrow.core.None
import arrow.core.Some
import arrow.core.identity
import arrow.core.right
import arrow.optics.optics
import arrow.syntax.function.compose
import arrow.syntax.function.partially2
import intcode.CurrentState
import intcode.IntCode
import intcode.handleCodePoint
import intcode.toIntCodeProgram
import java.util.*


@optics
data class DroneController(
    val code: IntCode,
    val state: Either<String, CurrentState> = CurrentState().right()
) {
    companion object
}

private tailrec fun DroneController.runCode(): DroneController {
    return when (state) {
        is Either.Left<String> -> this
        is Either.Right<CurrentState> -> when (state.b.pointer) {
            is None -> this
            is Some<Long> -> {
                copy(state = handleCodePoint(code, state)).runCode()
            }
        }
    }
}

object Day19 {
    private const val FILENAME = "src/main/resources/day19.txt"
    val fileData get() = FILENAME.toIntCodeProgram()


    val cache: MutableMap<PointL, Long> = mutableMapOf()

    fun findPowerAt(p: PointL): Long {
        return cache.getOrPut(p, {
            DroneController(
                code = fileData.toMutableMap(),
                state = CurrentState(
                    inputs = LinkedList(listOf(p.x, p.y))
                ).right()
            ).runCode().state.fold(
                { error("Unknonwn Problem at $p") },
                { state -> state.output.pop() })
        })
    }

    fun fourCorners(point: PointL, squareSize: Long) = listOf(
        ::identity,
        PointL.x::modify::partially2{ it + squareSize },
        PointL.x::modify::partially2{ it + squareSize } compose PointL.y::modify::partially2{ it - squareSize },
        PointL.y::modify::partially2{ it - squareSize }
    ).all { findPowerAt(it(point)) == 1L }

    fun part1() {
        cache.clear()
        println((0 until 50).flatMap { y ->
            (0 until 50).map { x ->
                PointL(x.toLong(), y.toLong())
            }
        }.map(::findPowerAt).count { it == 1L })
    }

    fun part2() {
        val squareSize = 99L
        cache.clear()
        val n = generateSequence(squareSize) { it + 1 }.map { y ->
            generateSequence(y * 0.7) { it + 1 }.takeWhile { it <= y }.map { x ->
                PointL(x.toLong(), y.toLong())
            }.dropWhile { findPowerAt(it) == 0L }.first()

        }.dropWhile { !fourCorners(it, squareSize) }.first()
        println(n.x * 10000 + n.y - squareSize)
    }
}

fun main() {
    Day19.part1()
    Day19.part2()
}