Skip to content

Commit 0405819

Browse files
committed
Solution 2025-10 part 1
1 parent 2a379fa commit 0405819

File tree

2 files changed

+136
-0
lines changed
  • src
    • main/kotlin/de/ronny_h/aoc/year2025/day10
    • test/kotlin/de/ronny_h/aoc/year2025/day10

2 files changed

+136
-0
lines changed
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
package de.ronny_h.aoc.year2025.day10
2+
3+
import de.ronny_h.aoc.AdventOfCode
4+
import de.ronny_h.aoc.extensions.memoize
5+
import de.ronny_h.aoc.year2025.day10.LightState.OFF
6+
import de.ronny_h.aoc.year2025.day10.LightState.ON
7+
8+
fun main() = Day10().run(481, 0)
9+
10+
class Day10 : AdventOfCode<Int>(2025, 10) {
11+
override fun part1(input: List<String>): Int {
12+
var i = 0
13+
return input.parseMachineDescriptions().sumOf {
14+
i++
15+
val result = Machine(it).configureIndicatorLights()
16+
println("machine $i: $result")
17+
result
18+
}
19+
}
20+
21+
override fun part2(input: List<String>): Int {
22+
return 0
23+
}
24+
}
25+
26+
// [.##.] (3) (1,3) (2) (2,3) (0,2) (0,1) {3,5,4,7}
27+
fun List<String>.parseMachineDescriptions(): List<MachineDescription> =
28+
map { line ->
29+
val indicatorLights = line.substringBefore("] (").drop(1)
30+
.map { if (it == '#') ON else OFF }
31+
val wiringSchematics = line.substringAfter("] ").substringBefore(" {")
32+
.split(" ").map { it.drop(1).dropLast(1).split(",").map(String::toInt) }
33+
val joltage = line.substringAfter(") {").dropLast(1).split(",").map(String::toInt)
34+
MachineDescription(indicatorLights, wiringSchematics, joltage)
35+
}
36+
37+
38+
data class MachineDescription(
39+
val indicatorLights: List<LightState>,
40+
val wiringSchematics: List<List<Int>>,
41+
val joltage: List<Int>
42+
)
43+
44+
enum class LightState {
45+
OFF, ON;
46+
47+
fun toggle() = when (this) {
48+
OFF -> ON
49+
ON -> OFF
50+
}
51+
}
52+
53+
class Machine(private val description: MachineDescription, private val maxPressCount: Int = 7) {
54+
private val indicatorLightsOff = List(description.indicatorLights.size) { OFF }
55+
private val buttons = description.wiringSchematics
56+
57+
// determine the fewest total presses
58+
fun configureIndicatorLights(): Int {
59+
val target = description.indicatorLights
60+
61+
data class RecursiveState(val state: List<LightState>, val buttonsToPress: List<Int>, val pressCount: Int)
62+
63+
lateinit var pressButtons: (RecursiveState) -> Int
64+
pressButtons = { s ->
65+
if (s.pressCount == maxPressCount) {
66+
maxPressCount
67+
} else {
68+
val newState = s.state.toMutableList()
69+
s.buttonsToPress.forEach { newState[it] = newState[it].toggle() }
70+
if (newState.contentEquals(target)) {
71+
s.pressCount
72+
} else {
73+
buttons.minOf { pressButtons(RecursiveState(newState.toList(), it, s.pressCount + 1)) }
74+
}
75+
}
76+
}
77+
78+
val pressButtonsMemoized = pressButtons.memoize()
79+
80+
return buttons.minOf { pressButtonsMemoized(RecursiveState(indicatorLightsOff, it, 1)) }
81+
}
82+
}
83+
84+
fun <T> MutableList<T>.contentEquals(other: List<T>): Boolean {
85+
if (size != other.size) return false
86+
forEachIndexed { i, element -> if (other[i] != element) return false }
87+
return true
88+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
package de.ronny_h.aoc.year2025.day10
2+
3+
import de.ronny_h.aoc.extensions.asList
4+
import de.ronny_h.aoc.year2025.day10.LightState.OFF
5+
import de.ronny_h.aoc.year2025.day10.LightState.ON
6+
import io.kotest.core.spec.style.StringSpec
7+
import io.kotest.matchers.shouldBe
8+
9+
class Day10Test : StringSpec({
10+
11+
val input = """
12+
[.##.] (3) (1,3) (2) (2,3) (0,2) (0,1) {3,5,4,7}
13+
[...#.] (0,2,3,4) (2,3) (0,4) (0,1,2) (1,2,3,4) {7,5,12,7,2}
14+
[.###.#] (0,1,2,3,4) (0,3,4) (0,1,2,4,5) (1,2) {10,11,11,5,10,5}
15+
""".asList()
16+
17+
"parse" {
18+
"""
19+
[.##.] (3) (1,3) {3,5,4}
20+
[.#] (0,2,3,4) {7,5}
21+
""".asList().parseMachineDescriptions() shouldBe listOf(
22+
MachineDescription(listOf(OFF, ON, ON, OFF), listOf(listOf(3), listOf(1, 3)), listOf(3, 5, 4)),
23+
MachineDescription(listOf(OFF, ON), listOf(listOf(0, 2, 3, 4)), listOf(7, 5)),
24+
)
25+
}
26+
27+
"contentEquals" {
28+
mutableListOf(1, 2).contentEquals(listOf(1, 2)) shouldBe true
29+
mutableListOf(1, 2).contentEquals(listOf(1, 2, 3)) shouldBe false
30+
mutableListOf(1, 2).contentEquals(listOf(1, 3)) shouldBe false
31+
}
32+
33+
"configureIndicatorLights" {
34+
val descriptions = input.parseMachineDescriptions()
35+
Machine(descriptions[0], 5).configureIndicatorLights() shouldBe 2
36+
Machine(descriptions[1], 5).configureIndicatorLights() shouldBe 3
37+
Machine(descriptions[2], 5).configureIndicatorLights() shouldBe 2
38+
}
39+
40+
"part 1" {
41+
Day10().part1(input) shouldBe 7
42+
}
43+
44+
"part 2" {
45+
val input = listOf("")
46+
Day10().part2(input) shouldBe 0
47+
}
48+
})

0 commit comments

Comments
 (0)