-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathDay8.kt
62 lines (53 loc) · 2.1 KB
/
Day8.kt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
package me.markrobbo
import me.markrobbo.HandheldGamesConsole.ExitCode
import me.markrobbo.HandheldGamesConsole.Instruction.OpCode
class HandheldGamesConsole(private val instructions: List<Instruction>) {
private var acc = 0
private var pc = 0
private var executed = mutableSetOf<Int>()
fun run(): Pair<Int, ExitCode> {
while (pc != instructions.size) {
if (executed.contains(pc)) {
return acc to ExitCode.INFINITE_LOOP
}
executed.add(pc)
val ir = instructions[pc]
when (ir.op) {
OpCode.ACC -> { acc += ir.arg.also { pc++ } }
OpCode.JMP -> { pc += ir.arg }
OpCode.NOP -> { pc++ }
}
}
return acc to ExitCode.SUCCESS
}
enum class ExitCode { INFINITE_LOOP, SUCCESS }
data class Instruction(val op: OpCode, val arg: Int) {
enum class OpCode { NOP, JMP, ACC }
}
}
class Day8 {
fun solvePart1(input: List<String>) = HandheldGamesConsole(parseInstructions(input)).run().first
fun solvePart2(input: List<String>): Int {
val instructions = parseInstructions(input)
return instructions.withIndex()
.filter { (_, instruction) -> instruction.op in listOf(OpCode.JMP, OpCode.NOP) }
.map { (i, instruction) ->
val newOp = when (instruction.op) {
OpCode.JMP -> OpCode.NOP
OpCode.NOP -> OpCode.JMP
else -> throw IllegalStateException()
}
val newInstructions = instructions.toMutableList().also { it[i] = it[i].copy(op = newOp) }
HandheldGamesConsole(newInstructions).run()
}
.first { it.second == ExitCode.SUCCESS }
.first
}
private fun parseInstructions(program: List<String>): List<HandheldGamesConsole.Instruction> {
return program.map { instruction ->
instruction.split(" ").let { (op, arg) ->
HandheldGamesConsole.Instruction(OpCode.valueOf(op.toUpperCase()), arg.toInt())
}
}
}
}