Jon Bristow

Posted on

# Advent of Code 2019 Solution Megathread - Day 17: Set and Forget

Gotta get rid of the dust before space-mom comes to see our space module!

### Day 17 - The Problem

Oh no! We need to save our robot helpers! There's a solar flare on the way, and we need to use our trusty IntCode interpreter to use the Aft Scaffolding Control and Information Interface to help find a sleepy robot to help us out.

Part 1 has us examining the scaffolding and calculating the value of a bunch of intersections.

Part 2 requires us to send some code into the IntCode interpreter to instruct a little robot to tell the rest of its friends to get inside.

### 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!

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.

#### Neat Statistics

I'm planning on adding some statistics, but other than "what languages did we see yesterday" does anyone have any ideas?

##### Languages Seen On Day 16

Under construction

## Top comments (2)

Rizwan

Forgot to post the solution here. I tried to solve the part 2 in code and I couldn't find any way of doing it. As usual got the hint from R website and went ahead on manual way.

Swift solution

``````func partOne() {
let computer = Opcode.init(input)
var result: String = ""
var outputs: [Int] = []
while !computer.done {
outputs.append(computer.run())
}
outputs.map { result.append(Character(UnicodeScalar(\$0)!))}

let grid = result.split(separator: "\n").map{ \$0.map{\$0}}
var sum = 0
for row in 1 ..< (grid.count - 1) {
for column in 1 ..< (grid[row].count - 1) {
if grid[row][column] == "#" {
if grid[row][column - 1] == "#" &&
grid[row][column + 1] == "#" &&
grid[row - 1][column] == "#" &&
grid[row + 1][column] == "#" {
sum += row * column
}
}
}
}
print(grid)
print("Part 1 answer is :\(sum)")
}

func partTwo() {
var scanLine = ""
let rules = """
A,B,B,A,B,C,A,C,B,C
L,4,L,6,L,8,L,12
L,8,R,12,L,12
R,12,L,6,L,6,L,8
y\n
""".map { Int(\$0.asciiValue!) }
var rulesIndex = -1

var dustCollected = 0
input[0] = 2
let computer = Opcode.init(input)
while !computer.done {
rulesIndex += 1
computer.inputIds.append(rules[rulesIndex])
let value = computer.run()
dustCollected = value
}

print("Part 2 answer is :\(dustCollected)")
}

partOne()
partTwo()
``````

Opcode and input can be found here

Jon Bristow • Edited

Woo! I got in the mid-900s for part 1!

However, part 2 doesn't seem to be working. It never asks for input and I don't know why! I was accidentally saving state between runs. DOH!

Kotlin solution for part 1

``````import arrow.core.Either
import arrow.core.None
import arrow.core.Some
import arrow.core.left
import arrow.core.right
import arrow.optics.optics
import intcode.CurrentState
import intcode.IntCode
import intcode.handleCodePoint
import intcode.toIntCodeProgram
import java.util.*

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

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

private fun Ascii.sendInput(): Ascii {
return state.fold(
ifLeft = { this },
ifRight = {
when {
it.waitingForInput && inputs.isEmpty() -> copy(state = "Error: Attempted to get input with no inputs left.".left())
it.waitingForInput -> {
val nInstr = inputs.pop()
copy(state = it.right())
}
else -> {
this
}
}
}
)
}

private tailrec fun Ascii.processOutput(): Ascii {
return when (state) {
is Either.Left<String> -> this
is Either.Right<CurrentState> -> when {
state.b.output.isEmpty() -> this
else -> {
val o = state.b.output.pop()
when {
o > 127 -> println("NONASCII:\$o")
else -> print(o.toChar())
}
if (o.toChar() == '\n') {
output.clear()
}

processOutput()
}
}
}
}

object Day17 {
private const val FILENAME = "src/main/resources/day17.txt"
val fileData = FILENAME.toIntCodeProgram()

fun part1() {
val ascii = Ascii(code = fileData).runCode()
println(ascii.output.joinToString("") { it.toChar().toString() })
val points = ascii.output.joinToString("") { l -> "\${l.toChar()}" }
.lines().mapIndexed { y, line ->
line.withIndex().filter { (_, c) -> c == '#' }
.map { (x, c) ->
Point(x, y) to c
}
}.flatten().toMap()
val intersections =
points.filterKeys { p -> allDirections().map { d -> p.inDirection(d) }.all(points::contains) }.keys

println(intersections.sumBy { p -> p.x * p.y })

}

val prog = "A,B,A,C,B,C,B,C,A,B\n" +
"L,6,L,4,R,8\n" +
"R,8,L,6,L,4,L,10,R,8\n" +
"L,4,R,4,L,4,R,8\n" +
"y\n"

fun part2() {
println(prog.lines().map { it.length })
println(prog.map { b -> b.toLong() })
val newCode = FILENAME.toIntCodeProgram().apply { this[0] = 2 }
val ascii = Ascii(
code = newCode,
inputs = LinkedList(prog.map { it.toLong() }),
state = CurrentState().right()
).runCode()

println(ascii)
}
}

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

``````