1
+ // Advent of Code 2024, Day 11.
2
+ // By Sebastian Raaphorst, 2024.
3
+
4
+ package day11
5
+
6
+ import common.aocreader.fetchAdventOfCodeInput
7
+ import common.parsing.WhitespaceParser
8
+ import common.runner.timedFunction
9
+ import day11.StoneRules.cacheSize
10
+ import java.util.concurrent.ConcurrentHashMap
11
+
12
+
13
+ private fun parse (input : String ): MutableMap <Long , Long > =
14
+ input.split(WhitespaceParser )
15
+ .map(String ::toLong)
16
+ .groupingBy { it }
17
+ .eachCount()
18
+ .mapValues { it.value.toLong() }
19
+ .toMutableMap()
20
+
21
+ // The key is that the order of the stones have no relevance.
22
+ private object StoneRules {
23
+ private val memoization: MutableMap <Long , List <Long >> = ConcurrentHashMap ()
24
+
25
+ private fun rule (stone : Long ): List <Long > = memoization.computeIfAbsent(stone) {
26
+ when {
27
+ it == 0L -> listOf (1L )
28
+ it.toString().length % 2 == 0 -> {
29
+ val middle = it.toString().length / 2
30
+ listOf (
31
+ it.toString().substring(0 , middle).toLong(),
32
+ it.toString().substring(middle).toLong()
33
+ )
34
+ }
35
+ else -> listOf (it * 2024 )
36
+ }
37
+ }
38
+
39
+ fun blink (stones : Map <Long , Long >): MutableMap <Long , Long > =
40
+ stones.flatMap { (stone, count) ->
41
+ rule(stone).map { transformed -> transformed to count }
42
+ }.groupingBy { it.first }
43
+ .fold(0L ) { acc, (_, count) -> acc + count }
44
+ .toMutableMap()
45
+
46
+ fun cacheSize (): Int = memoization.size
47
+ }
48
+
49
+ private fun answer (input : String , blinks : Int ): Long =
50
+ (1 .. blinks).fold(parse(input)) { stones, _ -> StoneRules .blink(stones) }
51
+ .values.sum()
52
+
53
+ fun answer1 (input : String ): Long =
54
+ answer(input, 25 )
55
+
56
+ fun answer2 (input : String ): Long =
57
+ answer(input, 75 )
58
+
59
+ fun main () {
60
+ val input = fetchAdventOfCodeInput(2024 , 11 )
61
+ println (" --- Day 11: Plutonian Pebbles ---" )
62
+ timedFunction(" Part 1" ) { answer1(input) }
63
+ println (" \t Cache size: ${cacheSize()} " )
64
+ timedFunction(" Part 2" ) { answer2(input) }
65
+ println (" \t Cache size: ${cacheSize()} " )
66
+ }
0 commit comments