-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathDay17ChronospatialComputer.kt
More file actions
105 lines (89 loc) · 3.27 KB
/
Day17ChronospatialComputer.kt
File metadata and controls
105 lines (89 loc) · 3.27 KB
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
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
package adventofcode.year2024
import adventofcode.Puzzle
import adventofcode.PuzzleInput
class Day17ChronospatialComputer(
customInput: PuzzleInput? = null,
) : Puzzle(customInput) {
private val registers by lazy { input.lines().take(3).map { it.substringAfter(": ").toLong() } }
private val program by lazy {
input
.lines()
.last()
.substringAfter(": ")
.split(",")
.map(String::toInt)
}
override fun partOne() = runProgram(program, registers).joinToString(",")
override fun partTwo() =
program
.reversed()
.map(Int::toLong)
.fold(listOf(0L)) { candidates, instruction ->
candidates.flatMap { candidate ->
val shifted = candidate shl 3
(shifted..shifted + 8).mapNotNull { registerA ->
registerA.takeIf { runProgram(program, listOf(registerA) + registers.drop(1)).first() == instruction }
}
}
}.first()
companion object {
private fun runProgram(
program: List<Int>,
registers: List<Long>,
): List<Long> {
var (registerA, registerB, registerC) = registers
var pointer = 0
val output = mutableListOf<Long>()
while (pointer < program.size - 1) {
val opcode = program[pointer]
val literalOperand = program[pointer + 1]
val comboOperand =
when (literalOperand) {
in 0..3 -> literalOperand.toLong()
4 -> registerA
5 -> registerB
6 -> registerC
else -> throw IllegalArgumentException("$literalOperand is not a valid combo operand")
}
when (opcode) {
0 -> {
registerA = registerA shr comboOperand.toInt()
pointer += 2
}
1 -> {
registerB = registerB xor literalOperand.toLong()
pointer += 2
}
2 -> {
registerB = comboOperand.mod(8L)
pointer += 2
}
3 -> {
pointer =
when (registerA) {
0L -> pointer + 2
else -> literalOperand
}
}
4 -> {
registerB = registerB xor registerC
pointer += 2
}
5 -> {
output += comboOperand.mod(8).toLong()
pointer += 2
}
6 -> {
registerB = registerA shr comboOperand.toInt()
pointer += 2
}
7 -> {
registerC = registerA shr comboOperand.toInt()
pointer += 2
}
}
}
return output
}
}
}