Skip to content

Commit 56f829d

Browse files
committed
Day 11
1 parent cdcdca2 commit 56f829d

File tree

4 files changed

+118
-0
lines changed

4 files changed

+118
-0
lines changed

src/main/kotlin/common/ext/Number.kt

+8
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
package common.ext
22

3+
import kotlin.math.floor
4+
import kotlin.math.log10
5+
36
fun Boolean.toInt() = if (this) 1 else 0
47

58
fun List<Int>.product() = fold(1) { a, b -> a * b }
@@ -26,3 +29,8 @@ inline fun <T> Iterable<T>.productOf(selector: (T) -> Long): Long {
2629
}
2730

2831
fun Int.divideRoundUp(divideBy: Int) = (this + divideBy - 1) / divideBy
32+
33+
fun Long.numDigits(): Int {
34+
if (this == 0L) return 1
35+
return log10(this.toDouble()).toInt() + 1
36+
}

src/main/kotlin/y24/Day11.kt

+70
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
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.splitToLongs
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 = 11, dryRun = false) { Day11(it) }
16+
17+
class Day11(val input: Input) : Puzzle {
18+
19+
data class Stone(
20+
val stone: Long,
21+
val amount: Long,
22+
)
23+
24+
private fun blinkOnce(stone: Long): List<Long> {
25+
if (stone == 0L) {
26+
return listOf(1L)
27+
}
28+
val digits = stone.numDigits()
29+
if (digits % 2 == 0) {
30+
// Split
31+
val str = stone.toString()
32+
val left = str.substring(0, digits / 2).toLong()
33+
val right = str.substring(digits / 2).toLong()
34+
return listOf(left, right)
35+
}
36+
37+
return listOf(stone * 2024)
38+
}
39+
40+
private fun blinkStones(stones: List<Stone>, n: Int): List<Stone> {
41+
if (n == 0) return stones
42+
43+
val newStones = mutableListOf<Stone>()
44+
stones.forEach { stone ->
45+
val blinked = blinkOnce(stone.stone)
46+
blinked.map { Stone(it, stone.amount) }.forEach { newStones += it }
47+
}
48+
49+
// Merge newStones
50+
val grouped = newStones
51+
.groupBy { it.stone }
52+
.map { (stone, group) ->
53+
Stone(stone, group.sumOf { it.amount })
54+
}
55+
56+
return blinkStones(grouped, n - 1)
57+
}
58+
59+
private val inputStones = input.lines[0]
60+
.splitToLongs(" ")
61+
.map { Stone(it, 1L) }
62+
63+
override fun solveLevel1(): Any {
64+
return blinkStones(inputStones, 25).sumOf { it.amount }
65+
}
66+
67+
override fun solveLevel2(): Any {
68+
return blinkStones(inputStones, 75).sumOf { it.amount }
69+
}
70+
}
+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package common.ext
2+
3+
import org.junit.jupiter.api.Test
4+
5+
import org.junit.jupiter.api.Assertions.*
6+
7+
internal class NumberTest {
8+
@Test
9+
fun numDigits() {
10+
assertEquals(1, 0.numDigits())
11+
assertEquals(1, 1.numDigits())
12+
assertEquals(1, 9.numDigits())
13+
assertEquals(2, 10.numDigits())
14+
assertEquals(2, 99.numDigits())
15+
assertEquals(3, 100.numDigits())
16+
}
17+
}

src/test/kotlin/y24/Day11Test.kt

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
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 Day11Test {
8+
private val sample = Input("""
9+
125 17
10+
""".trimIndent())
11+
12+
private val day = Day11(sample)
13+
14+
@Test
15+
fun solveLevel1() {
16+
assertEquals(55312L, day.solveLevel1())
17+
}
18+
19+
@Test
20+
fun solveLevel2() {
21+
// No sample
22+
}
23+
}

0 commit comments

Comments
 (0)