Advent of Code 2023 day 14
12/14/2024, 5:00 AMJan Durovec
12/14/2024, 5:48 AMMichael de Kaste
12/14/2024, 5:52 AMkingsley
12/14/2024, 5:57 AMMichael de Kaste
12/14/2024, 5:59 AMkingsley
12/14/2024, 6:02 AMNorbert Kiesel
12/14/2024, 6:08 AMNorbert Kiesel
12/14/2024, 6:11 AMJan Durovec
12/14/2024, 6:12 AMPetr Sýkora
12/14/2024, 6:13 AMNorbert Kiesel
12/14/2024, 6:14 AMkingsley
12/14/2024, 6:15 AMJan Durovec
12/14/2024, 6:17 AMNorbert Kiesel
12/14/2024, 6:17 AMJonathan Kolberg
12/14/2024, 6:18 AMNorbert Kiesel
12/14/2024, 6:20 AMJonathan Kolberg
12/14/2024, 6:21 AMMarcin Wisniowski
12/14/2024, 6:23 AMMarcin Wisniowski
12/14/2024, 6:24 AMJonathan Kolberg
12/14/2024, 6:24 AMJan Durovec
12/14/2024, 6:25 AMJonathan Kolberg
12/14/2024, 6:25 AMMarcin Wisniowski
12/14/2024, 6:26 AMMichael de Kaste
12/14/2024, 6:26 AMoperator fun Pair<Int, Int>.rem(other: Pair<Int, Int>)
I have a feeling we might need to use that again in the featureMarcin Wisniowski
12/14/2024, 6:28 AMextractInts()
util, seems super useful.Michael de Kaste
12/14/2024, 6:29 AMRegex("""-?\d+""").findAll(input)
Michael de Kaste
12/14/2024, 6:29 AMbj0
12/14/2024, 6:35 AMbj0
12/14/2024, 6:38 AMbj0
12/14/2024, 6:39 AM/\
and printing them out until i spotted what the pattern looked like, then i changed my search to 10 robots in a horizontal lineAleksandr Pilipenko
12/14/2024, 6:41 AMbj0
12/14/2024, 6:42 AMDan Fingal-Surma
12/14/2024, 6:42 AMDan Fingal-Surma
12/14/2024, 6:42 AMDan Fingal-Surma
12/14/2024, 6:42 AMMichael de Kaste
12/14/2024, 6:42 AMDan Fingal-Surma
12/14/2024, 6:44 AMAleksandr Pilipenko
12/14/2024, 6:44 AMDan Fingal-Surma
12/14/2024, 6:46 AMbj0
12/14/2024, 6:46 AMDan Fingal-Surma
12/14/2024, 6:47 AMDan Fingal-Surma
12/14/2024, 6:47 AMbj0
12/14/2024, 6:47 AMDan Fingal-Surma
12/14/2024, 6:48 AMMichael de Kaste
12/14/2024, 6:48 AMMichael de Kaste
12/14/2024, 6:49 AMMichael de Kaste
12/14/2024, 6:50 AMDan Fingal-Surma
12/14/2024, 6:50 AMDan Fingal-Surma
12/14/2024, 6:50 AMDan Fingal-Surma
12/14/2024, 6:50 AMDan Fingal-Surma
12/14/2024, 6:51 AMDan Fingal-Surma
12/14/2024, 6:51 AMbj0
12/14/2024, 6:51 AMMichael de Kaste
12/14/2024, 6:51 AMMichael de Kaste
12/14/2024, 6:51 AMAleksandr Pilipenko
12/14/2024, 6:51 AMimagine me scrolling through an output.txt file with HEIGHT * 14224Someone did almost that 😄
Michael de Kaste
12/14/2024, 6:52 AMMichael de Kaste
12/14/2024, 7:03 AMAnirudh
12/14/2024, 7:05 AMEndre Deak
12/14/2024, 7:08 AMMichael de Kaste
12/14/2024, 7:09 AMDan Fingal-Surma
12/14/2024, 7:16 AMEndre Deak
12/14/2024, 7:20 AMpart2() {
var i = 0
// input: List<Robot>, Robot has pos and velocity fields
while(input.size != input.map { it.pos }.toSet().size) {
input.forEach { it.move(w, h, 1) }
i++
}
print() // print the tiles to see the tree
i
}
Endre Deak
12/14/2024, 7:36 AMPaul Woitaschek
12/14/2024, 7:43 AMJakub Gwóźdź
12/14/2024, 8:05 AMJakub Gwóźdź
12/14/2024, 8:06 AMLuan Tran
12/14/2024, 8:08 AMAnirudh
12/14/2024, 8:08 AMLuan Tran
12/14/2024, 8:10 AMLuan Tran
12/14/2024, 8:14 AMJakub Gwóźdź
12/14/2024, 8:17 AMAnirudh
12/14/2024, 8:18 AMAnirudh
12/14/2024, 8:22 AMgroupBy { (point, _) -> grid.quadrant(point) }
which was a simple when clause:
private fun Grid<Int>.quadrant(point: Point): Int? = when (point) {
in 0..<midX to 0..<midY -> 0
in midX + 1..<cols to 0..<midY -> 1
in 0..<midX to midY + 1..<rows -> 2
in midX + 1..<cols to midY + 1..<rows -> 3
else -> null
}
Jakub Gwóźdź
12/14/2024, 8:23 AMDue to a unit conversion error, the room is actuallyhigher on both the10000000000000
andX
axis!Y
Luan Tran
12/14/2024, 8:24 AMJakub Gwóźdź
12/14/2024, 8:27 AMfun Pos.quadrant(bounds: Pos) = when {
first < bounds.first / 2 && second < bounds.second / 2 -> 0
first > bounds.first / 2 && second < bounds.second / 2 -> 1
first < bounds.first / 2 && second > bounds.second / 2 -> 2
first > bounds.first / 2 && second > bounds.second / 2 -> 3
else -> null
}
then
.groupingBy { (p, v) -> p.quadrant(boundary) }.eachCount()
.filterKeys { it != null }
.values.fold(1, Int::times)
Anirudh
12/14/2024, 8:29 AMspace: Pair<IntRange, IntRange> = Pair(0..<cols, 0..<rows)
but didn't need it (modulo does it).
and for the quadrant check, I added overloads for Points in Pair-of-ranges; which I will now move the the common utils 🙂
operator fun Pair<IntRange, IntRange>.contains(point: Point) =
point.x in this.first && point.y in this.second
Jakub Gwóźdź
12/14/2024, 8:29 AM.fold(0, Int::times)
instead of .fold(1, Int::times)
at the beginning, and spend good chunk of time figuring out which of the quadrants has 0 robots and why 🙂Jakub Gwóźdź
12/14/2024, 8:32 AM.reduce(...)
instead 🙂phldavies
12/14/2024, 8:37 AMprivate fun List<Robot>.isChristmasTree(): Boolean =
distinctBy { it.px to it.py }.size == size
?Jakub Gwóźdź
12/14/2024, 8:45 AMNorbert Kiesel
12/14/2024, 8:46 AMJakub Gwóźdź
12/14/2024, 8:47 AMgenerateSequence(input) { robots -> robots.step(boundary) }
.indexOfFirst { robots -> robots.map { it.first }.distinct().size == input.size }
Luan Tran
12/14/2024, 8:49 AMNeil Banman
12/14/2024, 8:53 AMAnirudh
12/14/2024, 8:54 AMNeil Banman
12/14/2024, 8:54 AMPaul Woitaschek
12/14/2024, 8:54 AMNeil Banman
12/14/2024, 8:55 AMAnirudh
12/14/2024, 8:56 AMphldavies
12/14/2024, 9:00 AMrobotsInSpace
methodPaul Woitaschek
12/14/2024, 9:00 AMLuan Tran
12/14/2024, 9:02 AMNeil Banman
12/14/2024, 9:02 AMif
statements with duplicative clauses, like:
if (p.x in 0 until splitX && p.y in 0 until splitY) {...}
x6
But I don't like that either.Luan Tran
12/14/2024, 9:09 AMfun quadrant(robots: List<Point>, size: Point) =
robots.partition { it.first in 0 until size.first / 2 }
.toList().flatMap {
it.partition { it.second in 0 until size.second / 2 }.toList()
}
Luan Tran
12/14/2024, 9:11 AMNeil Banman
12/14/2024, 9:11 AMLuan Tran
12/14/2024, 9:12 AMLuan Tran
12/14/2024, 9:12 AMAnirudh
12/14/2024, 9:13 AMNeil Banman
12/14/2024, 9:16 AMAnirudh
12/14/2024, 9:26 AMAnirudh
12/14/2024, 9:28 AMJakub Gwóźdź
12/14/2024, 9:29 AMPaul Woitaschek
12/14/2024, 9:30 AMAnirudh
12/14/2024, 9:31 AMPaul Woitaschek
12/14/2024, 9:32 AMphldavies
12/14/2024, 9:33 AMDan Fingal-Surma
12/14/2024, 10:53 AMAnirudh
12/14/2024, 10:59 AMDan Fingal-Surma
12/14/2024, 11:03 AMprivate fun List<Robot>.score(): Int {
val quadrants = IntArray(4)
val splitX = width / 2
val splitY = height / 2
for (p in this) {
val index = when {
p.x < splitX && p.y < splitY -> 0
p.x < splitX && p.y > spliyY -> 1
p.x > splitX && p.y < splitY -> 2
p.x > splitX && p.y > splitY -> 3
else -> continue
}
quadrants[index]++
}
return quadrants.reduce(Int::times)
}
Dan Fingal-Surma
12/14/2024, 11:13 AMfun List<Robot>.score(room: Point): Int {
val xMid = room.x / 2
val yMid = room.y / 2
return count { it.x < xMid && it.y < yMid } *
count { it.x < xMid && it.y > yMid } *
count { it.x > xMid && it.y < yMid } *
count { it.x > xMid && it.y > yMid }
}
Dan Fingal-Surma
12/14/2024, 11:15 AMDan Fingal-Surma
12/14/2024, 11:16 AMMax Thiele
12/14/2024, 11:17 AMfun countNeighbors(): Int {
val positions = robots.map { it.pos }.toSet()
return positions.count { it + Vec2i(1, 0) in positions }
}
And search for a neighbor count > 100Dan Fingal-Surma
12/14/2024, 11:27 AMAnirudh
12/14/2024, 11:40 AM(bot.pos + bot.vel * times).mod(Point(cols, rows))
but those functions always create new points (I mean, I'm creating new Bots anyway). Point is data class Point(val x: Int, val y: Int)
with those operator functions
so would this kind of optimisation be useful?
(bot.pos.x + bot.vel.x * times).mod(cols)
(bot.pos.y + bot.vel.y * times).mod(rows)
Paul Woitaschek
12/14/2024, 11:43 AMAnirudh
12/14/2024, 11:44 AMJaap Beetstra
12/14/2024, 11:46 AMPaul Woitaschek
12/14/2024, 11:48 AMJaap Beetstra
12/14/2024, 11:55 AMDan Fingal-Surma
12/14/2024, 12:13 PMDan Fingal-Surma
12/14/2024, 12:15 PMJakub Gwóźdź
12/14/2024, 12:17 PMJakub Gwóźdź
12/14/2024, 12:25 PMAnirudh
12/14/2024, 12:25 PMShreck Ye
12/14/2024, 1:06 PMLazyVerticleGrid
with Compose, went through them all but it turned out to be not helpful. Eventually I managed to find the answer in some other way, and its corresponding image appears to be just common. Maybe my input is more peculiar. 😂Anirudh
12/14/2024, 1:42 PMephemient
12/14/2024, 3:17 PMIf you're wondering when the picture appears, just wait until the robots do not collide (i.e. are at unique positions)@Jan Durovec that does not work for my input
ephemient
12/14/2024, 3:17 PMJakub Gwóźdź
12/14/2024, 3:30 PMJosh Soberg
12/14/2024, 4:39 PMAnirudh
12/14/2024, 6:49 PMJakub Gwóźdź
12/14/2024, 6:59 PMAnirudh
12/14/2024, 7:00 PMAnirudh
12/14/2024, 7:01 PMtimes * velocity
with negative times
would work. I'll do 9000 backward to check 😉Jakub Gwóźdź
12/14/2024, 7:02 PMAnirudh
12/14/2024, 7:04 PMgenerateSequence(0) { it - 1 }
with drop(9000) take(1) ✅
or just generateSequence(-9000) { it - 1 }
take(1)Jakub Gwóźdź
12/14/2024, 7:06 PM(p + v * count) % boundary
:)
And here's my image converterAnirudh
12/14/2024, 7:07 PM(bot.pos + bot.vel * times).mod(Point(cols, rows))
(btw, it's missing one bot at the bottom right of the border. but it was auto-generated from the PNG, )nerses
12/14/2024, 8:21 PM......*......
.....*.*.....
....*...*....
...*.....*...
..*.......*..
I don't like relying on the fact of no overlapping to find the tree. The input could have well been created with collisions.
Also my input produces several grids with 0 collisions which don't have the Xmas tree in them
here is my codeCharles Flynn
12/14/2024, 8:32 PMAnirudh
12/14/2024, 8:37 PMAnirudh
12/15/2024, 4:32 AMephemient
01/06/2025, 1:07 PMt in 0..<width
when the most robots are in the same +x/-x half
• look for the time t in 0..<height
when the most robots are in the same +y/-y half
• as it's all linear, these repeat every width
and height
timesteps respectively
• then it's just a simple linear diophantine equation to solve for the time when the robots are mostly in the same +x/-x and +y/-y quadrant
implemented in https://github.com/ephemient/aoc2024/commit/ddd5f1706dc1745484b2091a6f945a0dc4905f2f, and since it requires far fewer steps, it clocks in at about 600x faster than my previous "scan all times for the longest lines" approach