-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathDay11.kt
85 lines (67 loc) · 2.78 KB
/
Day11.kt
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
package tr.emreone.adventofcode.days
import tr.emreone.kotlin_utils.Resources
import tr.emreone.kotlin_utils.automation.Day
class Day11 : Day(
11,
2024,
"Plutonian Pebbles",
session = Resources.resourceAsString("session.cookie")
) {
override fun part1(): Int {
val initialStones = inputAsString.split("\\s+".toRegex()).map { it.toLong() }
val blinks = 25
val finalStones = evolveStones(initialStones, blinks)
return finalStones.size
}
override fun part2(): Long {
val initialStones = inputAsString.split("\\s+".toRegex()).map { it.toLong() }
val blinks = 75
val finalStones = evolveStonesEfficiently(initialStones, blinks)
return finalStones.values.sum()
}
private fun evolveStones(stones: List<Long>, blinks: Int): List<Long> {
var currentStones = stones
repeat(blinks) {
val newStones = mutableListOf<Long>()
for (stone in currentStones) {
when {
stone == 0L -> newStones.add(1L)
stone.toString().length % 2 == 0 -> {
val mid = stone.toString().length / 2
val left = stone.toString().substring(0, mid).toLong()
val right = stone.toString().substring(mid).toLong()
newStones.add(left)
newStones.add(right)
}
else -> newStones.add(stone * 2024L)
}
}
currentStones = newStones
}
return currentStones
}
private fun evolveStonesEfficiently(stones: List<Long>, blinks: Int): Map<Long, Long> {
var currentStones = stones.groupingBy { it }.eachCount().mapValues { it.value.toLong() }
repeat(blinks) {
val newStones = mutableMapOf<Long, Long>()
for ((stone, count) in currentStones) {
when {
stone == 0L -> newStones[1L] = newStones.getOrDefault(1L, 0L) + count
stone.toString().length % 2 == 0 -> {
val mid = stone.toString().length / 2
val left = stone.toString().substring(0, mid).toLong()
val right = stone.toString().substring(mid).toLong()
newStones[left] = newStones.getOrDefault(left, 0L) + count
newStones[right] = newStones.getOrDefault(right, 0L) + count
}
else -> {
val newStone = stone * 2024
newStones[newStone] = newStones.getOrDefault(newStone, 0L) + count
}
}
}
currentStones = newStones
}
return currentStones
}
}