Skip to content

Commit 4080e10

Browse files
authored
Day 17 2024 (#279)
1 parent 18ab796 commit 4080e10

File tree

4 files changed

+118
-0
lines changed

4 files changed

+118
-0
lines changed
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
package me.peckb.aoc._2024.calendar.day17
2+
3+
import javax.inject.Inject
4+
import me.peckb.aoc.generators.InputGenerator.InputGeneratorFactory
5+
import kotlin.math.pow
6+
7+
class Day17 @Inject constructor(
8+
private val generatorFactory: InputGeneratorFactory,
9+
) {
10+
fun partOne(filename: String) = generatorFactory.forFile(filename).read { input ->
11+
val computer = Computer.fromInput(input)
12+
val output = runProgram(computer)
13+
output.joinToString(",")
14+
}
15+
16+
fun partTwo(filename: String) = generatorFactory.forFile(filename).read { input ->
17+
val computer = Computer.fromInput(input)
18+
19+
findProgram(computer, computer.operations.map{ it.toLong() })
20+
}
21+
22+
private fun findProgram(computer: Computer, target: List<Long>): Long {
23+
var aStart = if (target.size > 1) {
24+
8 * findProgram(computer, target.drop(1))
25+
} else { 0 }
26+
27+
while(runProgram(computer.copy(aReg = aStart)) != target) {
28+
aStart++
29+
}
30+
31+
return aStart
32+
}
33+
34+
private fun runProgram(c: Computer): List<Long> {
35+
val output = mutableListOf<Long>()
36+
var programPointer = 0
37+
38+
while(programPointer < c.operations.size - 1) {
39+
val opcode = c.operations[programPointer]
40+
val operand = c.operations[programPointer + 1]
41+
42+
programPointer += 2
43+
44+
val comboOperand by lazy {
45+
when (operand) {
46+
0, 1, 2, 3 -> operand.toLong()
47+
4 -> c.aReg
48+
5 -> c.bReg
49+
6 -> c.cReg
50+
else -> throw IllegalArgumentException("Invalid operand: $operand")
51+
}
52+
}
53+
54+
when (opcode) {
55+
0 -> c.aReg = (c.aReg / 2.0.pow(comboOperand.toDouble())).toLong()
56+
1 -> c.bReg = c.bReg xor operand.toLong()
57+
2 -> c.bReg = comboOperand % 8
58+
3 -> if (c.aReg != 0L) { programPointer = operand }
59+
4 -> c.bReg = c.bReg xor c.cReg
60+
5 -> output.add(comboOperand % 8)
61+
6 -> c.bReg = (c.aReg / 2.0.pow(comboOperand.toDouble())).toLong()
62+
7 -> c.cReg = (c.aReg / 2.0.pow(comboOperand.toDouble())).toLong()
63+
}
64+
}
65+
66+
return output
67+
}
68+
}
69+
70+
data class Computer(var aReg: Long, var bReg: Long, var cReg: Long, val operations: List<Int>) {
71+
companion object {
72+
fun fromInput(input: Sequence<String>): Computer {
73+
val data = input.toList()
74+
val aReg = data[0].split("A: ")[1].toLong()
75+
val bReg = data[1].split("B: ")[1].toLong()
76+
val cReg = data[2].split("C: ")[1].toLong()
77+
78+
val program = data[4].split(": ")[1].split(",").map { it.toInt() }
79+
80+
return Computer(aReg, bReg, cReg, program)
81+
}
82+
}
83+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
## [Day 17: Chronospatial Computer](https://adventofcode.com/2024/day/17)

src/test/kotlin/me/peckb/aoc/_2024/TestDayComponent.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import me.peckb.aoc._2024.calendar.day13.Day13Test
1616
import me.peckb.aoc._2024.calendar.day14.Day14Test
1717
import me.peckb.aoc._2024.calendar.day15.Day15Test
1818
import me.peckb.aoc._2024.calendar.day16.Day16Test
19+
import me.peckb.aoc._2024.calendar.day17.Day17Test
1920
import javax.inject.Singleton
2021
import me.peckb.aoc.DayComponent
2122
import me.peckb.aoc.InputModule
@@ -40,4 +41,5 @@ internal interface TestDayComponent : DayComponent {
4041
fun inject(day14Test: Day14Test)
4142
fun inject(day15Test: Day15Test)
4243
fun inject(day16Test: Day16Test)
44+
fun inject(day17Test: Day17Test)
4345
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package me.peckb.aoc._2024.calendar.day17
2+
3+
import javax.inject.Inject
4+
5+
import me.peckb.aoc._2024.DaggerTestDayComponent
6+
import org.junit.jupiter.api.Assertions.assertEquals
7+
import org.junit.jupiter.api.BeforeEach
8+
import org.junit.jupiter.api.Test
9+
10+
internal class Day17Test {
11+
@Inject
12+
lateinit var day17: Day17
13+
14+
@BeforeEach
15+
fun setup() {
16+
DaggerTestDayComponent.create().inject(this)
17+
}
18+
19+
@Test
20+
fun testDay17PartOne() {
21+
assertEquals("2,7,6,5,6,0,2,3,1", day17.partOne(DAY_17))
22+
}
23+
24+
@Test
25+
fun testDay17PartTwo() {
26+
assertEquals(107_416_870_455_451, day17.partTwo(DAY_17))
27+
}
28+
29+
companion object {
30+
private const val DAY_17: String = "advent-of-code-input/2024/day17.input"
31+
}
32+
}

0 commit comments

Comments
 (0)