-
-
Save joelburton/6b00b69e36d61824e5a077ed346f9a8c to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.io.File | |
/** Single instruction for state machine. */ | |
data class Instruction(val opcode: String, val operand: Int) | |
/** Marker exception raised during state machine runs. */ | |
class Answer(val result: Int) : Throwable() | |
val lines = File("8.txt") | |
.readLines() | |
.map { it.split(" ") } | |
.map { (opcode, operand) -> Instruction(opcode, operand.toInt()) } | |
/** Run state machine, throwing result when loop detected. */ | |
fun toLoop(acc: Int = 0, ip: Int = 0, ipSeen: Set<Int> = setOf()) { | |
if (ip in ipSeen) throw Answer(acc) | |
val (opcode, operand) = lines[ip] | |
return when (opcode) { | |
"acc" -> toLoop(acc + operand, ip + 1, ipSeen + ip) | |
"jmp" -> toLoop(acc, ip + operand, ipSeen + ip) | |
"nop" -> toLoop(acc, ip + 1, ipSeen + ip) | |
else -> throw IllegalStateException() | |
} | |
} | |
/** Run state machine to after final line, throwing accum when we reach there. | |
* | |
* This can branch exactly one time: a single jmp/nop can be switched. | |
*/ | |
fun toEnd( | |
acc: Int = 0, | |
ip: Int = 0, | |
ipSeen: Set<Int> = setOf(), | |
fixed: Boolean = false | |
) { | |
if (ip in ipSeen) return | |
if (ip > lines.lastIndex) throw Answer(acc) | |
val (opcode, operand) = lines[ip] | |
when (opcode) { | |
"acc" -> toEnd(acc + operand, ip + 1, ipSeen + ip, fixed) | |
"jmp" -> { | |
toEnd(acc, ip + operand, ipSeen + ip, fixed) | |
if (!fixed) toEnd(acc, ip + 1, ipSeen + ip, true) | |
} | |
"nop" -> { | |
toEnd(acc, ip + 1, ipSeen + ip, fixed) | |
if (!fixed) toEnd(acc, ip + operand, ipSeen + ip, true) | |
} | |
else -> throw IllegalStateException() | |
} | |
} | |
fun main() { | |
try { toLoop() } catch (exc: Answer) { println(exc.result) } | |
try { toEnd() } catch (exc: Answer) { println(exc.result) } | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment