Skip to content

Commit 66afa06

Browse files
committed
Day 17
1 parent 4380fc5 commit 66afa06

File tree

2 files changed

+168
-0
lines changed

2 files changed

+168
-0
lines changed

src/main/kotlin/y24/Day17.kt

+135
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
package y24
2+
3+
import common.puzzle.solvePuzzle
4+
import common.puzzle.Input
5+
import common.puzzle.Puzzle
6+
import common.datastructures.*
7+
import common.ext.*
8+
import common.puzzle.splitToInts
9+
import common.util.*
10+
import java.util.*
11+
import kotlin.math.*
12+
import kotlin.system.exitProcess
13+
14+
15+
fun main() = solvePuzzle(year = 2024, day = 17, dryRun = true) { Day17(it) }
16+
17+
data class Computer(
18+
var a: Long,
19+
var b: Long,
20+
var c: Long,
21+
) {
22+
var output: MutableList<Int> = mutableListOf()
23+
}
24+
25+
fun Computer.readCombo(combo: Int): Long {
26+
return when (combo) {
27+
4 -> a
28+
5 -> b
29+
6 -> c
30+
else -> combo.toLong()
31+
}
32+
}
33+
34+
fun Computer.run(program: List<Int>, requireOutput: List<Int>?): Boolean {
35+
var pointer = 0
36+
while (pointer in program.indices) {
37+
val instr = Instruction.entries[program[pointer]]
38+
val value = program[pointer + 1]
39+
instr.op(this, value)?.let {
40+
pointer = it
41+
} ?: run { pointer += 2 }
42+
43+
if (instr == Instruction.Out && requireOutput != null) {
44+
if (output.last() != requireOutput[output.size - 1]) {
45+
return false
46+
}
47+
}
48+
}
49+
50+
return requireOutput?.let { it.size == output.size } ?: true
51+
}
52+
53+
enum class Instruction(val op: (Computer, Int) -> Int?) {
54+
Adv({ comp, combo ->
55+
comp.a = comp.a shr comp.readCombo(combo).toInt()
56+
null
57+
}),
58+
Bxl({ comp, literal ->
59+
comp.b = comp.b xor literal.toLong()
60+
null
61+
}),
62+
Bst({ comp, combo ->
63+
comp.b = comp.readCombo(combo) % 8
64+
null
65+
}),
66+
Jnz({ comp, literal ->
67+
if (comp.a == 0L) {
68+
null
69+
} else {
70+
literal
71+
}
72+
}),
73+
Bxc({ comp, _ ->
74+
comp.b = comp.b xor comp.c
75+
null
76+
}),
77+
Out({ comp, combo ->
78+
comp.output += (comp.readCombo(combo) % 8).toInt()
79+
null
80+
}),
81+
Bdv({ comp, combo ->
82+
comp.b = comp.a shr comp.readCombo(combo).toInt()
83+
null
84+
}),
85+
Cdv({ comp, combo ->
86+
comp.c = comp.a shr comp.readCombo(combo).toInt()
87+
null
88+
})
89+
}
90+
91+
class Day17(val input: Input) : Puzzle {
92+
93+
private fun parseInput(lines: List<String>): Pair<Computer, List<Int>> {
94+
val a = lines[0].substringAfter(": ").toLong()
95+
val b = lines[1].substringAfter(": ").toLong()
96+
val c = lines[2].substringAfter(": ").toLong()
97+
val program = lines[4].substringAfter(": ")
98+
.splitToInts()
99+
return Computer(a, b, c) to program
100+
}
101+
102+
override fun solveLevel1(): Any {
103+
val (computer, program) = parseInput(input.lines)
104+
computer.run(program, requireOutput = null)
105+
return computer.output.joinToString(",")
106+
}
107+
108+
// Program:
109+
// b = (a % 8) xor 1
110+
// c = a / 2^b = a >> b
111+
// b = b xor 5 xor c
112+
// out(b % 8)
113+
// a = a / 2^3 = a >> 3
114+
private fun findA(program: List<Int>, from: Int): Long {
115+
var a = if (from == program.size - 1) {
116+
0
117+
} else {
118+
findA(program, from + 1) shl 3
119+
}
120+
121+
while (true) {
122+
val comp = Computer(a, 0, 0)
123+
if (comp.run(program, program.subList(from, program.size))) {
124+
return a
125+
}
126+
127+
a++
128+
}
129+
}
130+
131+
override fun solveLevel2(): Any {
132+
val (_, program) = parseInput(input.lines)
133+
return findA(program, 0)
134+
}
135+
}

src/test/kotlin/y24/Day17Test.kt

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package y24
2+
3+
import common.puzzle.Input
4+
import org.junit.jupiter.api.Assertions.assertEquals
5+
import org.junit.jupiter.api.Test
6+
7+
internal class Day17Test {
8+
private val sample = Input("""
9+
Register A: 729
10+
Register B: 0
11+
Register C: 0
12+
13+
Program: 0,1,5,4,3,0
14+
""".trimIndent())
15+
16+
private val day = Day17(sample)
17+
18+
@Test
19+
fun solveLevel1() {
20+
assertEquals("4,6,3,5,6,3,5,2,1,0", day.solveLevel1())
21+
}
22+
23+
@Test
24+
fun solveLevel2() {
25+
assertEquals(117440L, Day17(Input("""
26+
Register A: 2024
27+
Register B: 0
28+
Register C: 0
29+
30+
Program: 0,3,5,4,3,0
31+
""".trimIndent())).solveLevel2())
32+
}
33+
}

0 commit comments

Comments
 (0)