Advent of Code 2023 day 25
12/25/2024, 5:00 AMJonathan Kolberg
12/25/2024, 5:21 AMbj0
12/25/2024, 5:23 AMMarcin Wisniowski
12/25/2024, 5:35 AMAnirudh
12/25/2024, 5:35 AMList<List<T>>.transponse()
by now.
would have made the 'create column heights' a simple heights.count { it == '#'}
Marcin Wisniowski
12/25/2024, 5:36 AMJakub Gwóźdź
12/25/2024, 5:39 AMtypealias Input = Pair<List<List<Int>>, List<List<Int>>>
fun part1(input: Input): Int = input.let { (keys, locks) ->
locks.sumOf { lock ->
keys.count { key -> key.zip(lock).all { (k, l) -> k >= l } }
}
}
fun parse(text: String): Input = text.lines().chunked(8).let { chunks ->
val keys = mutableListOf<List<Int>>()
val locks = mutableListOf<List<Int>>()
chunks.forEach { chunk ->
val isKey = chunk[0] == "....."
val isLock = chunk[0] == "#####"
check(isKey xor isLock) { "Invalid chunk: $chunk" }
val counts = (0..4).map { col ->
chunk.filterNot { it.isBlank() }
.count { row -> row[col] == if (isLock) '#' else '.' }
}
if (isLock) locks.add(counts) else keys.add(counts)
}
keys to locks
}
Anirudh
12/25/2024, 5:42 AMJakub Gwóźdź
12/25/2024, 5:45 AMAnirudh
12/25/2024, 5:45 AM3,0,2,0,1
fits on two different locks and the lock 1,2,0,5,3
works with two keys.
so can't use an any or first because he wants all combosAnirudh
12/25/2024, 5:47 AM1 2 2 2 4
with 1 2 2 0 4
then the LSB carries over but then 2 + 2 or 2 + 3 fits so would not be an error/overflow (but it should not be counted)Michael de Kaste
12/25/2024, 5:48 AMkingsley
12/25/2024, 5:51 AMMichael de Kaste
12/25/2024, 5:52 AMJakub Gwóźdź
12/25/2024, 6:01 AMfun part1(input: Input): Int = input.let { (keys, locks) ->
var count = 0
for (key in keys) {
for (lock in locks) {
val valid = key <= lock &&
key and 7 <= lock and 7 &&
key and 63 <= lock and 63 &&
key and 511 <= lock and 511 &&
key and 4095 <= lock and 4095
if (valid) count++
}
}
count
}
but that can be tweaked even furtherAnirudh
12/25/2024, 6:05 AMfor + for + all
is actually O(n^3) with early exit
locksHeights.sumOf { lockH ->
keysHeights.count { keyH ->
lockH.zip(keyH).all { (lh, kh) -> lh + kh < rows - 1 }
}
}
Anirudh
12/25/2024, 6:05 AMnested 5 deep sortedmap@Michael de Kaste hehe I have no idea what that is 🙃
Jakub Gwóźdź
12/25/2024, 6:11 AMfun part1(input: Input): Int = input.let { (keys, locks) ->
var count = 0
val legit = 0b1110111011101110111
for (key in keys)
for (lock in locks)
if ((lock - key) or legit == legit) count++
count
}
parsing also takes 35us 🙂
chunks.forEach { chunk ->
val isKey = chunk[0] == "....."
val isLock = chunk[0] == "#####"
check(isKey xor isLock) { "Invalid chunk: $chunk" }
val keyCode = (0..4).map { col ->
chunk.filterNot { it.isBlank() }
.count { row -> row[col] == if (isLock) '.' else '#' }
}.fold(0) { acc, i -> acc * 16 + i }
if (isLock) locks.add(keyCode) else keys.add(keyCode)
}
ephemient
12/25/2024, 6:18 AMMichael de Kaste
12/25/2024, 6:32 AMMichael de Kaste
12/25/2024, 6:34 AMPaul Woitaschek
12/25/2024, 6:41 AMAndriy
12/25/2024, 6:41 AMtypealias Lock = List<Int>
typealias Key = List<Int>
I'm a bit wandered as this solution is fast on task data. I've expected long time matching and was ready doing tree-matching optimization 🫠Andriy
12/25/2024, 6:44 AMPaul Woitaschek
12/25/2024, 6:46 AMJakub Gwóźdź
12/25/2024, 7:01 AMMichael de Kaste
12/25/2024, 7:12 AMAnirudh
12/25/2024, 7:12 AMso it's idk... O(n*logn*logn*logn*logn*logn)?that's nice but when N=5, logn*logn*logn*logn*logn = 10.7 so n * logn...5 times = ~53 but N^2 = 25 🙂
Michael de Kaste
12/25/2024, 7:12 AMJakub Gwóźdź
12/25/2024, 7:12 AMMichael de Kaste
12/25/2024, 7:13 AMAnirudh
12/25/2024, 7:13 AMit's not N=5. N is a number of locks, not pinsah, yes. my bad
Jakub Gwóźdź
12/25/2024, 7:14 AMMichael de Kaste
12/25/2024, 7:15 AMMichael de Kaste
12/25/2024, 7:19 AMMichael de Kaste
12/25/2024, 7:19 AMJakub Gwóźdź
12/25/2024, 7:20 AMMichael de Kaste
12/25/2024, 7:21 AMMichael de Kaste
12/25/2024, 7:21 AMMichael de Kaste
12/25/2024, 7:29 AMO(n * width * height log height)
whereas the double loop solution is O(n² * width)
Dan Fingal-Surma
12/25/2024, 8:05 AMDan Fingal-Surma
12/25/2024, 8:05 AMDan Fingal-Surma
12/25/2024, 8:06 AMDan Fingal-Surma
12/25/2024, 8:06 AMDan Fingal-Surma
12/25/2024, 8:10 AMHCP
12/25/2024, 8:32 AMHCP
12/25/2024, 8:32 AMHCP
12/25/2024, 8:34 AMphldavies
12/25/2024, 9:37 AM@AoKSolution
object Day25 {
context(PuzzleInput) fun part1() = parse {
it.combinations(2).count { (a, b) -> a and b == 0 }
}
val parse = Parser {
input.split("\n\n").map {
it.fold(0) { acc, c ->
when (c) {
'#' -> acc shl 1 or 1
'.' -> acc shl 1
else -> acc
}
}
}
}
}
happy BitMas everyone advent of code intensifiesphldavies
12/25/2024, 10:07 AMJakub Gwóźdź
12/25/2024, 10:08 AMphldavies
12/25/2024, 10:09 AMJakub Gwóźdź
12/25/2024, 10:30 AMO(n*6^5)
solution (ok in reality it's much less than 6^5, but it's upper bound)
Thanks @Michael de Kaste @Dan Fingal-Surma
// part1 but O(n*6^5)
fun part2(input: Input): Int {
val locks = BitSet(6 * 6 * 6 * 6 * 6)
input.forEach { chunk ->
if (chunk[0] == "#####") locks.set(keyCode(chunk, '.', 6))
}
var count = 0
input.forEach { chunk ->
if (chunk[0] != "#####") {
val (k0,k1,k2,k3,k4) = heights(chunk, '#')
for (l0 in k0..6) {
for (l1 in k1..6) {
for (l2 in k2..6) {
for (l3 in k3..6) {
for (l4 in k4..6) {
val keyCode = keyCode(listOf(l0, l1, l2, l3, l4), 6)
if( locks.get(keyCode)) count++
}
}
}
}
}
}
}
return count
}
private fun heights(chunk: List<String>, c: Char) = (0..4).map { col -> chunk.count { row -> row[col] == c } }
private fun keyCode(heights: List<Int>, base: Int) = heights.fold(0) { acc, i -> acc * base + i - 1}
private fun keyCode(chunk: List<String>, c: Char, base: Int) = keyCode(heights(chunk, c), base)
Jakub Gwóźdź
12/25/2024, 10:31 AM// O(n^2)
fun part1(input: Input): Int {
var count = 0
val legit = 0b1110111011101110111
val keys = mutableListOf<Int>()
val locks = mutableListOf<Int>()
input.forEach { chunk ->
val isLock = chunk[0] == "#####"
if (isLock) {
val keyCode = keyCode(chunk, '.', 16)
count += keys.count { (keyCode - it) or legit == legit }
locks.add(keyCode)
} else {
val keyCode = keyCode(chunk, '#', 16)
// for (lock in locks) if ((lock - keyCode) or legit == legit) count++
count += locks.count { (it - keyCode) or legit == legit }
keys.add(keyCode)
}
}
return count
}
Marcin Wisniowski
12/25/2024, 3:19 PMDan Fingal-Surma
12/25/2024, 10:04 PMDan Fingal-Surma
12/25/2024, 10:49 PMDan Fingal-Surma
12/25/2024, 10:50 PMDan Fingal-Surma
12/25/2024, 10:50 PMDan Fingal-Surma
12/25/2024, 10:51 PMDan Fingal-Surma
12/25/2024, 10:52 PMDan Fingal-Surma
12/25/2024, 10:54 PMDan Fingal-Surma
12/25/2024, 11:13 PMDan Fingal-Surma
12/26/2024, 12:25 AMDan Fingal-Surma
12/26/2024, 12:27 AMDan Fingal-Surma
12/26/2024, 12:27 AM