Advent of Code 2023 day 22
12/22/2024, 5:00 AMDan Fingal-Surma
12/22/2024, 5:54 AMRenette Ros
12/22/2024, 5:56 AMDan Fingal-Surma
12/22/2024, 5:56 AMMichael de Kaste
12/22/2024, 5:59 AMRenette Ros
12/22/2024, 6:00 AMDan Fingal-Surma
12/22/2024, 6:00 AMDan Fingal-Surma
12/22/2024, 6:01 AMMichael de Kaste
12/22/2024, 6:01 AMonConflict: (T, T) -> T
functionMichael de Kaste
12/22/2024, 6:02 AMDan Fingal-Surma
12/22/2024, 6:03 AMDan Fingal-Surma
12/22/2024, 6:03 AMMichael de Kaste
12/22/2024, 6:07 AMmap[x] = y
is functionally the same as array[x] = y
but I just think association could use a 'what if you want to recalculate the value`. I understand that, this is what 'groupingBy' does -> do not actually use a list, but define what you want.
I just feel like groupingBy was introduced at Kotlin's start lifecycle and never got retouched with the same love as the normal Sequence/Iteratable functions doDan Fingal-Surma
12/22/2024, 6:07 AMreveresed
will produce the first one wins behavior. Will try it when I'm back in a computerMichael de Kaste
12/22/2024, 6:08 AMDan Fingal-Surma
12/22/2024, 6:08 AMDan Fingal-Surma
12/22/2024, 6:09 AMMichael de Kaste
12/22/2024, 6:10 AMDan Fingal-Surma
12/22/2024, 6:13 AMDan Fingal-Surma
12/22/2024, 6:13 AMDan Fingal-Surma
12/22/2024, 6:27 AMforEach
and collect
have different namesbj0
12/22/2024, 6:35 AMbj0
12/22/2024, 6:37 AMbj0
12/22/2024, 6:40 AMMarcin Wisniowski
12/22/2024, 6:41 AMkingsley
12/22/2024, 6:43 AMshl 10
instead of shl 11
for the multiplied by 2048 and this ended up taking over 30 minutes to debug 🤦♂️
I tried to be smart with part 2 and failed woefully, so my final solution ends up taking about 4 seconds to compute. I'm curious if there's a smart way to speed this upMax Thiele
12/22/2024, 6:46 AMJonathan Kolberg
12/22/2024, 6:49 AMMarcin Wisniowski
12/22/2024, 6:52 AMDispatchers.Default
, otherwise your async
is not doing much.Jonathan Kolberg
12/22/2024, 6:54 AMJakub Gwóźdź
12/22/2024, 7:04 AMJakub Gwóźdź
12/22/2024, 7:05 AMfun <T, R> List<T>.mapParallel(op: (T) -> R) = runBlocking { map { async(Dispatchers.Default) { op(it) } }.awaitAll() }
for the rescue 🙂Dan Fingal-Surma
12/22/2024, 7:06 AMDan Fingal-Surma
12/22/2024, 7:07 AMDan Fingal-Surma
12/22/2024, 7:18 AMAnirudh
12/22/2024, 7:43 AMdata class Changes(a, b, c, d)
but I think it would be better to just build a Unified map on the first pass itself 🤔 with the values being added to a list, or just the sum directly 💡
will do that nowHCP
12/22/2024, 7:44 AMfun getSequences(priceList: List<List<Int>>): List<Map<List<Int>, Int>> {
val sequences = mutableListOf<MutableMap<List<Int>, Int>>()
priceList.forEachIndexed { i, list ->
sequences.add(mutableMapOf())
list.forEachIndexed { j, price ->
if (j >= 4) {
val sequence = listOf(
list[j-3]-list[j-4],
list[j-2]-list[j-3],
list[j-1]-list[j-2],
list[j]-list[j-1])
if (!sequences[i].containsKey(sequence)) sequences[i][sequence] = price
}
}
}
return sequences
}
which is easily solved using built-in Kotlin functionality?Jakub Gwóźdź
12/22/2024, 8:12 AM.toString()
-edAnirudh
12/22/2024, 8:14 AMMichael de Kaste
12/22/2024, 8:16 AM.reduce{ acc, it -> acc shl 5 + it + 9 }
?Michael de Kaste
12/22/2024, 8:16 AMJakub Gwóźdź
12/22/2024, 8:19 AMphldavies
12/22/2024, 8:19 AMJakub Gwóźdź
12/22/2024, 8:19 AMJakub Gwóźdź
12/22/2024, 8:20 AMJakub Gwóźdź
12/22/2024, 8:21 AMacc*100+it
works for that reductionAnirudh
12/22/2024, 8:25 AMChanges(a, b, c, d) to chg.last().first
to
"$a,$b,$c,$d" to chg.last().first
and it's gone up to 1.3 secs, from 1.0 secs.
but I'm not benchmarking correctly. just using measureTime
Jakub Gwóźdź
12/22/2024, 8:27 AMJakub Gwóźdź
12/22/2024, 8:28 AMAnirudh
12/22/2024, 8:30 AMAnirudh
12/22/2024, 8:32 AMphldavies
12/22/2024, 8:52 AMzipWithNext(Long::minus)
into "$a $b $c $d"
is the fastest (I'm using distinctBy
to take only the first instance seen in the sequence)
BenchDay22.dataClass avgt 3 1.065 ± 0.129 s/op
BenchDay22.destructureToString avgt 3 0.516 ± 0.473 s/op
BenchDay22.joinToString avgt 3 0.867 ± 0.142 s/op
BenchDay22.list avgt 3 1.462 ± 0.142 s/op
BenchDay22.reduce avgt 3 0.705 ± 0.227 s/op
Dan Fingal-Surma
12/22/2024, 9:34 AMDan Fingal-Surma
12/22/2024, 10:09 AM4354313
hash map entriesJakub Gwóźdź
12/22/2024, 10:11 AMDan Fingal-Surma
12/22/2024, 10:12 AMDan Fingal-Surma
12/22/2024, 10:13 AMJakub Gwóźdź
12/22/2024, 10:15 AM3000000
max?Dan Fingal-Surma
12/22/2024, 10:16 AMAnirudh
12/22/2024, 10:16 AMAnirudh
12/22/2024, 10:19 AMDan Fingal-Surma
12/22/2024, 10:25 AMJakub Gwóźdź
12/22/2024, 10:45 AM1,-1,1,-1,1
.
But it's big enough percentage to justify counting in IntArray(20*20*20*20*20) { 0 }
instead of a hashMapDan Fingal-Surma
12/22/2024, 10:46 AMphldavies
12/22/2024, 10:46 AMArray<Array<Array<IntArray>>>
)
Warming up 2 puzzles for 10s each for year 2024 day 22...
Acc warmed up with 74 iterations
Default warmed up with 21 iterations
year 2024 day 22 part 1
Array took 22.518514ms 👑: 16039090236
Default took 24.194791ms (1.07x): 16039090236
year 2024 day 22 part 2
Array took 134.197583ms 👑: 1808
Default took 455.922416ms (3.40x): 1808
Jonathan Kolberg
12/22/2024, 10:46 AMIntArray(19*19*19*19*19) { 0 }
is enoughtJakub Gwóźdź
12/22/2024, 10:47 AMphldavies
12/22/2024, 10:47 AMJakub Gwóźdź
12/22/2024, 10:48 AMprivate fun Long.nextSecret(): Long = step1().step2().step3()
private fun Long.step1() = shl(6) xor this and 0xFFFFFF
private fun Long.step2() = shr(5) xor this and 0xFFFFFF
private fun Long.step3() = shl(11) xor this and 0xFFFFFF
it might be enlightening to print all the numbers in sequence in binary 🙂Anirudh
12/22/2024, 10:52 AMDan Fingal-Surma
12/22/2024, 10:52 AMfun encode(deltas: List<Int>) = ((deltas[0] + 10) shl 15) or ((deltas[1] + 10) shl 10) or ((deltas[2] + 10) shl 5) or ((deltas[3] + 10))
Dan Fingal-Surma
12/22/2024, 10:52 AMphldavies
12/22/2024, 10:54 AMdeltas.reduce { acc, delta -> acc shl 5 or (delta and 0x1F) }
?Michael de Kaste
12/22/2024, 10:54 AMpart2 {
val bananas = Array(19){ Array(19){ Array(19){ IntArray(19) } } }
val visited = Array(19){ Array(19){ Array(19){ Array(19){ BitSet(secrets.size) } } } }
var max = 0
secrets.forEachIndexed { index, line ->
line.map { it % 10 }.windowed(5){ (a,b,c,d,e) ->
val ax = b - a + 9
val bx = c - b + 9
val cx = d - c + 9
val dx = e - d + 9
if(!visited[ax][bx][cx][dx].get(index)){
bananas[ax][bx][cx][dx] += e
visited[ax][bx][cx][dx].set(index)
if(bananas[ax][bx][cx][dx] > max){
max = bananas[ax][bx][cx][dx]
}
}
}
}
max
}
It speeds up my part2 to 213.419400ms
Could be even faster with classic for loopsphldavies
12/22/2024, 10:55 AMcontext(PuzzleInput) fun part2(): Int {
val bananas = Array(19) { Array(19) { Array(19) { IntArray(19) } } }
val seen = Array(19) { Array(19) { Array(19) { IntArray(19) { -1 } } } }
var max = 0
Parsers.Longs().forEachIndexed { buyer, secret ->
generateSequence(secret) { it.evolve() }
.map { it % 10 }.take(2001)
.windowed(5) { (a, b, c, d, e) ->
val i = (e - d).mod(19)
val j = (d - c).mod(19)
val k = (c - b).mod(19)
val l = (b - a).mod(19)
if (seen[i][j][k][l] != buyer) {
seen[i][j][k][l] = buyer
bananas[i][j][k][l] += e.toInt()
max = maxOf(bananas[i][j][k][l], max)
}
}
.count()
}
return max
}
was my take, @Michael de KasteMichael de Kaste
12/22/2024, 10:56 AMJakub Gwóźdź
12/22/2024, 10:58 AMJakub Gwóźdź
12/22/2024, 11:04 AMDan Fingal-Surma
12/22/2024, 11:05 AMDan Fingal-Surma
12/22/2024, 11:05 AMJakub Gwóźdź
12/22/2024, 11:05 AMJakub Gwóźdź
12/22/2024, 11:05 AMDan Fingal-Surma
12/22/2024, 11:19 AM.map { (a, b, c, d) -> a.mod(19) * 6859 + b.mod(19) * 361 + c.mod(19) * 19 + d.mod(19) }
from
.map { (a, b, c, d) -> "$a $b $c $d" }
saves 300-400msDan Fingal-Surma
12/22/2024, 11:21 AMIntArray(19 * 19 * 19 * 19) { 0 }
is clean enough and saves a further 250 msJakub Gwóźdź
12/22/2024, 11:24 AMfun part2(input: Input): Any {
val array = IntArray(19 * 19 * 19 * 19 * 19)
val done = BooleanArray(19 * 19 * 19 * 19 * 19)
input.forEach { seed ->
done.fill(false)
generateSequence(seed, Long::nextSecret)
.map { it % 10 }
.take(2001)
.windowed(5)
.forEach { last5 ->
val code = last5.zipWithNext { a, b -> b - a }.fold(0L) { acc, l -> acc * 19 + l + 9 }.toInt()
if (!done[code]) {
done[code] = true
array[code] += last5.last().toInt()
}
}
}
return array.max()
}
makes it in 300ms (+/- 10%)Max Thiele
12/22/2024, 11:29 AMPart 1 median: 7.035 ms (709 benchmark iterations)
Part 2 median: 7.179 ms (676 benchmark iterations)
Dan Fingal-Surma
12/22/2024, 11:30 AMDan Fingal-Surma
12/22/2024, 11:44 AMDan Fingal-Surma
12/22/2024, 12:01 PMJakub Gwóźdź
12/22/2024, 12:05 PMDan Fingal-Surma
12/22/2024, 12:10 PMDan Fingal-Surma
12/22/2024, 12:11 PMDan Fingal-Surma
12/22/2024, 12:11 PMkingsley
12/22/2024, 12:47 PMCold
Part1: ~24ms. Part2: ~180ms
Warm
Part1: ~7ms. Part2: ~94ms
kingsley
12/22/2024, 12:54 PMlist.slice(a..b)
with list.subList(a, b+1)
and saved a few extra millisecondsephemient
12/22/2024, 1:56 PMit might be enlightening to print all the numbers in sequence in binary 🙂good luck with that 😉 https://en.wikipedia.org/wiki/Xorshift
Jakub Gwóźdź
12/22/2024, 2:04 PMphldavies
12/22/2024, 4:23 PMWarming up 2 puzzles for 10s each for year 2024 day 22...
Array warmed up with 520 iterations
Default warmed up with 22 iterations
year 2024 day 22 part 1
Array took 7.885264ms 👑: 16039090236
Default took 15.524028ms (1.97x): 16039090236
year 2024 day 22 part 2
Array took 11.130472ms 👑: 1808
Default took 449.944569ms (40.42x): 1808
I think I'm done now - single threaded, no coroutines.Jakub Gwóźdź
12/22/2024, 4:24 PMphldavies
12/22/2024, 4:26 PMcontext(PuzzleInput) fun part2(): Int {
val len = 0xFFFFF
val bananas = IntArray(len)
val seen = IntArray(len) { -1 }
var max = 0
for ((buyer, secret) in Parsers.Longs().withIndex()) {
var s = secret
var prevPrice = (s % 10).toInt()
var delta = 0
for (i in 0..<2000) {
s = s.evolve()
val price = (s % 10).toInt()
delta = (delta shl 5 and 0xFFFFF) or (9 + price - prevPrice)
prevPrice = price
if (i >= 3 && seen[delta] < buyer) {
seen[delta] = buyer
val newBananas = bananas[delta] + price
bananas[delta] = newBananas
max = maxOf(newBananas, max)
}
}
}
return max
}
nope - just abusing a nice large sparse array and some bit twiddlingDan Fingal-Surma
12/22/2024, 6:54 PMphldavies
12/22/2024, 6:56 PMkingsley
12/22/2024, 7:03 PMphldavies
12/22/2024, 7:05 PMkingsley
12/22/2024, 7:06 PMval map = IntArray(608850)
for (n in input) for ((k, v) in sequences(n)) map[k] += v
println(map.max())
phldavies
12/22/2024, 7:07 PMphldavies
12/22/2024, 7:08 PMkingsley
12/22/2024, 7:08 PMphldavies
12/22/2024, 7:09 PMkingsley
12/22/2024, 7:10 PMphldavies
12/22/2024, 7:12 PMkingsley
12/22/2024, 7:14 PMkingsley
12/22/2024, 7:15 PMphldavies
12/22/2024, 7:15 PMkingsley
12/22/2024, 7:16 PMDan Fingal-Surma
12/22/2024, 8:55 PMDan Fingal-Surma
12/22/2024, 8:58 PMDan Fingal-Surma
12/22/2024, 8:58 PMDan Fingal-Surma
12/22/2024, 8:59 PMDan Fingal-Surma
12/22/2024, 9:00 PMDan Fingal-Surma
12/22/2024, 9:05 PMkingsley
12/22/2024, 9:15 PM{ 0 }
and { false }
when initializing the int and Boolean arraysDan Fingal-Surma
12/22/2024, 9:16 PMkingsley
12/22/2024, 9:18 PMDan Fingal-Surma
12/22/2024, 9:51 PMDan Fingal-Surma
12/22/2024, 9:53 PM.toIntArray()
after .toList()
on prices saves a good 15-20msDan Fingal-Surma
12/22/2024, 9:53 PMDan Fingal-Surma
12/22/2024, 9:54 PM+ 9
instead of .mod(19)
also saves another 15-20msDan Fingal-Surma
12/22/2024, 10:03 PMDan Fingal-Surma
12/22/2024, 10:03 PMval prices = IntArray(2001)
var v = s
for (i in 0..2000) {
prices[i] = (v % 10).toInt()
v = next(v)
}
Dan Fingal-Surma
12/22/2024, 10:39 PMDan Fingal-Surma
12/22/2024, 10:46 PM(v xor s) % (1 shl 24)
to
(v xor s) and 0xFFFFFF
Dan Fingal-Surma
12/22/2024, 10:47 PMDan Fingal-Surma
12/22/2024, 10:57 PM