Skip to content

Commit 70fbb99

Browse files
committed
Vastly improve d22 runtime
I keep doing this, don't I
1 parent 982a772 commit 70fbb99

File tree

3 files changed

+77
-20
lines changed

3 files changed

+77
-20
lines changed

src/main/kotlin/sschr15/aocsolutions/Day22.kt

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,17 @@
11
package sschr15.aocsolutions
22

33
import sschr15.aocsolutions.util.*
4+
import java.util.concurrent.ConcurrentHashMap
45

56
/**
67
* AOC 2024 [Day 22](https://adventofcode.com/2024/day/22)
7-
* Challenge:
8+
* Challenge: There's a *very* competitive hide-and-seek game going on between a bunch of monkeys, so much so
9+
* that the auction house is full of prospective hiders
810
*/
911
object Day22 : Challenge {
1012
override fun solve() = challenge(2024, 22) {
1113
// test()
12-
14+
1315
val nums: List<Int>
1416
part1 {
1517
inputLines.ints().map {
@@ -23,28 +25,29 @@ object Day22 : Challenge {
2325
}.also { nums = it }.sumOf { it.toLong() }
2426
}
2527
part2 {
26-
val buyers = inputLines.ints().map {
27-
val outputs = sequence {
28-
var n = it
29-
repeat(2000) {
30-
n = n xor (n shl 6) and 0xffffff
31-
n = n xor (n ushr 5) and 0xffffff
32-
n = n xor (n shl 11) and 0xffffff
33-
yield(n)
34-
}
28+
val counts = ConcurrentHashMap<List<Int>, Int>()
29+
30+
inputLines.ints().forEachParallel { it ->
31+
val outputs = (0..2000).runningFold(it) { acc, _ ->
32+
var n = acc
33+
n = n xor (n shl 6) and 0xffffff
34+
n = n xor (n ushr 5) and 0xffffff
35+
n = n xor (n shl 11) and 0xffffff
36+
n
3537
}
3638

3739
val prices = outputs.map { it % 10 }
3840
val diffs = prices.windowed(2) { (a, b) -> b - a }
3941
val windows = diffs.windowed(4)
40-
val output = mutableMapOf<List<Int>, Int>()
41-
prices.drop(4).zip(windows).forEach { (price, window) ->
42-
if (window !in output) output[window] = price
42+
val seen = mutableSetOf<List<Int>>()
43+
for ((price, window) in prices.drop(4).zip(windows)) {
44+
if (seen.add(window)) {
45+
counts.merge(window, price, Int::plus)
46+
}
4347
}
44-
output
4548
}
4649

47-
buyers.flatMap { it.entries }.groupBy({ it.key }) { it.value }.maxOf { it.value.sum() }
50+
counts.maxOf { it.value }.also { check(it == 2423) }
4851
}
4952
}
5053

src/main/kotlin/sschr15/aocsolutions/util/IterableUtils.kt

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,9 @@ package sschr15.aocsolutions.util
44

55
import it.unimi.dsi.fastutil.objects.Object2IntMap
66
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap
7-
import kotlinx.coroutines.Dispatchers
8-
import kotlinx.coroutines.async
9-
import kotlinx.coroutines.awaitAll
7+
import kotlinx.coroutines.*
108
import kotlinx.coroutines.flow.Flow
119
import kotlinx.coroutines.flow.FlowCollector
12-
import kotlinx.coroutines.runBlocking
1310
import java.math.BigDecimal
1411
import java.math.BigInteger
1512
import java.util.*
@@ -134,6 +131,22 @@ inline fun <T, R> Iterable<T>.mapIndexedParallel(crossinline transform: suspend
134131
mapIndexed { index, t -> async(Dispatchers.Default) { transform(index, t) } }.awaitAll()
135132
}
136133

134+
inline fun <T> Iterable<T>.forEachParallel(crossinline action: suspend (T) -> Unit) {
135+
runBlocking {
136+
withContext(Dispatchers.Default) {
137+
forEach { async { action(it) } }
138+
}
139+
}
140+
}
141+
142+
inline fun <T> Iterable<T>.forEachIndexedParallel(crossinline action: suspend (Int, T) -> Unit) {
143+
runBlocking {
144+
withContext(Dispatchers.Default) {
145+
forEachIndexed { index, t -> async { action(index, t) } }
146+
}
147+
}
148+
}
149+
137150
inline fun <K, V> Iterable<Map<K, V>>.combineMaps(): Map<K, List<V>> {
138151
val result = mutableMapOf<K, MutableList<V>>()
139152
for (map in this) {

src/main/kotlin/sschr15/aocsolutions/util/SequenceUtils.kt

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,3 +62,44 @@ inline fun <T> Sequence<T>.noneIndexed(predicate: (Int, T) -> Boolean): Boolean
6262
}
6363
return true
6464
}
65+
66+
class LimitedSequence<T>(
67+
limit: Int,
68+
private val first: T = NOT_INITIALIZED as T,
69+
private val generateFirst: () -> T = { error("No generation passed") },
70+
private val generateNext: (T) -> T
71+
) : Iterator<T> {
72+
private var current = if (first === NOT_INITIALIZED) generateFirst() else first
73+
private var left = limit
74+
75+
override fun hasNext(): Boolean {
76+
return left > 0
77+
}
78+
79+
override fun next(): T {
80+
if (left-- <= 0) throw NoSuchElementException()
81+
val result = current
82+
current = generateNext(current)
83+
return result
84+
}
85+
86+
companion object {
87+
private val NOT_INITIALIZED = Any()
88+
}
89+
}
90+
91+
fun <T> generateLimitedSequence(limit: Int, seed: T, generateNext: (T) -> T): Sequence<T> {
92+
return object : Sequence<T> {
93+
override fun iterator(): Iterator<T> {
94+
return LimitedSequence(limit, seed, generateNext = generateNext)
95+
}
96+
}
97+
}
98+
99+
fun <T> generateLimitedSequence(limit: Int, generateFirst: () -> T, generateNext: (T) -> T): Sequence<T> {
100+
return object : Sequence<T> {
101+
override fun iterator(): Iterator<T> {
102+
return LimitedSequence(limit, generateFirst = generateFirst, generateNext = generateNext)
103+
}
104+
}
105+
}

0 commit comments

Comments
 (0)