Skip to content

Instantly share code, notes, and snippets.

@emiflake
Last active December 5, 2019 16:30
Show Gist options
  • Save emiflake/0b46e22df4b3c71b4200fa8b1b179e40 to your computer and use it in GitHub Desktop.
Save emiflake/0b46e22df4b3c71b4200fa8b1b179e40 to your computer and use it in GitHub Desktop.
import java.io.File
import java.util.stream.Stream
import kotlin.streams.toList
import kotlin.system.measureNanoTime
import kotlin.system.measureTimeMillis
sealed class IntCode {
abstract val steps: Int
object Halt : IntCode() {
override val steps = 1
override fun toString() = "Halt"
}
data class Add(val a: Loc, val b: Loc, val out: Loc.Ref) : IntCode() {
override val steps = 4
override fun toString() = "Add($a, $b, $out)"
}
data class Mul(val a: Loc, val b: Loc, val out: Loc.Ref) : IntCode() {
override val steps = 4
override fun toString() = "Mul($a, $b, $out)"
}
data class Input(val out: Loc.Ref) : IntCode() {
override val steps = 2
override fun toString() = "Input($out)"
}
data class Output(val out: Loc) : IntCode() {
override val steps = 2
override fun toString() = "Output($out)"
}
data class JumpIfTrue(val bool: Loc, val jmpLoc: Loc) : IntCode() {
override val steps = 3
override fun toString() = "JumpIfTrue($bool, $jmpLoc)"
}
data class JumpIfFalse(val bool: Loc, val jmpLoc: Loc) : IntCode() {
override val steps = 3
override fun toString() = "JumpIfFalse($bool, $jmpLoc)"
}
data class Less(val a: Loc, val b: Loc, val out: Loc.Ref) : IntCode() {
override val steps = 4
override fun toString() = "Less($a, $b, $out)"
}
data class Equals(val a: Loc, val b: Loc, val out: Loc.Ref) : IntCode() {
override val steps = 4
override fun toString() = "Equals($a, $b, $out)"
}
}
sealed class Loc {
data class Im(val value: Int) : Loc()
data class Ref(val ref: Int) : Loc()
fun get(memory: IntArray) = when (this) {
is Im -> this.value
is Ref -> memory[this.ref]
}
}
fun Int.digits(take: Long) =
Stream.iterate(this) { it.div(10) }
.limit(take)
.toList()
.reversed()
.map { it.rem(10) }
fun getCode(ip: Int, memory: IntArray): IntCode {
val raw = memory[ip]
val (c,b,a,d,e) = raw.digits(5)
fun lda(im: Int, offset: Int) = when (im) {
0 -> Loc.Ref(memory[ip + offset])
1 -> Loc.Im(memory[ip + offset])
else -> error("???")
}
val inst = d * 10 + e
return when (inst) {
1 -> IntCode.Add(lda(a, 1), lda(b, 2), Loc.Ref(memory[ip + 3]))
2 -> IntCode.Mul(lda(a, 1), lda(b, 2), Loc.Ref(memory[ip + 3]))
3 -> IntCode.Input(Loc.Ref(memory[ip + 1]))
4 -> IntCode.Output(lda(a, 1))
5 -> IntCode.JumpIfTrue(lda(a, 1), lda(b, 2))
6 -> IntCode.JumpIfFalse(lda(a, 1), lda(b, 2))
7 -> IntCode.Less(lda(a, 1), lda(b, 2), Loc.Ref(memory[ip + 3]))
8 -> IntCode.Equals(lda(a, 1), lda(b, 2), Loc.Ref(memory[ip + 3]))
99 -> IntCode.Halt
else -> error("Unknown opcode $inst")
}
}
fun runMachine(input: Int, memory: IntArray) {
var ip = 0
loop@ while (true) {
val opcode = getCode(ip, memory)
when (opcode) {
is IntCode.Add -> memory[opcode.out.ref] = opcode.a.get(memory) + opcode.b.get(memory)
is IntCode.Mul -> memory[opcode.out.ref] = opcode.a.get(memory) * opcode.b.get(memory)
is IntCode.Input -> memory[opcode.out.ref] = input
is IntCode.Output -> println(opcode.out.get(memory))
is IntCode.JumpIfTrue -> if (opcode.bool.get(memory) != 0) ip = opcode.jmpLoc.get(memory) - opcode.steps else Unit
is IntCode.JumpIfFalse -> if (opcode.bool.get(memory) == 0) ip = opcode.jmpLoc.get(memory) - opcode.steps else Unit
is IntCode.Less -> memory[opcode.out.ref] = if (opcode.a.get(memory) < opcode.b.get(memory)) 1 else 0
is IntCode.Equals -> memory[opcode.out.ref] = if (opcode.a.get(memory) == opcode.b.get(memory)) 1 else 0
IntCode.Halt -> break@loop
}
ip += opcode.steps
}
}
fun main() {
val memory = File("input.txt").readLines().first().split(",").map { it.toInt() }.toIntArray()
var avgPart1: Long = 0
var avgPart2: Long = 0
for (i in 1..100) {
avgPart1 += measureTimeMillis { runMachine(1, memory.clone()) }
avgPart2 += measureTimeMillis { runMachine(5, memory.clone()) }
}
println("Time of Part 01: ${avgPart1.toDouble() / 100} ms")
println("Time of Part 02: ${avgPart2.toDouble() / 100} ms")
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment