Skip to content

Commit 9ebaba6

Browse files
committed
solve 21st day 1st task
1 parent 1fb1e97 commit 9ebaba6

File tree

1 file changed

+105
-0
lines changed
  • year2024/src/main/kotlin/net/olegg/aoc/year2024/day21

1 file changed

+105
-0
lines changed
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
package net.olegg.aoc.year2024.day21
2+
3+
import net.olegg.aoc.someday.SomeDay
4+
import net.olegg.aoc.utils.Directions
5+
import net.olegg.aoc.utils.Vector2D
6+
import net.olegg.aoc.utils.find
7+
import net.olegg.aoc.utils.get
8+
import net.olegg.aoc.utils.permutations
9+
import net.olegg.aoc.year2024.DayOf2024
10+
11+
/**
12+
* See [Year 2024, Day 21](https://adventofcode.com/2024/day/21)
13+
*/
14+
object Day21 : DayOf2024(21) {
15+
private val pattern = "(\\d+)".toRegex()
16+
private val digits = """
17+
789
18+
456
19+
123
20+
0A
21+
""".trimIndent().lines().map { it.toList() }
22+
private val arms = """
23+
^A
24+
<v>
25+
""".trimIndent().lines().map { it.toList() }
26+
27+
override fun first(): Any? {
28+
val digitsMap = digits.flatMapIndexed { y, row ->
29+
row.mapIndexedNotNull { x, c ->
30+
if (c != ' ') c to Vector2D(x, y) else null
31+
}
32+
}.toMap()
33+
34+
return lines.sumOf { line ->
35+
val code = pattern.find(line)?.value?.toIntOrNull() ?: 0
36+
37+
val length = "A$line"
38+
.zipWithNext { a, b -> bestPath(digits, arms, digitsMap[a]!!, digitsMap[b]!!, 0) }
39+
.sum()
40+
41+
code * length
42+
}
43+
}
44+
45+
private val bestCache = mutableMapOf<Triple<Vector2D, Vector2D, Int>, Int>()
46+
47+
private fun bestPath(
48+
matrix: List<List<Char>>,
49+
handler: List<List<Char>>,
50+
from: Vector2D,
51+
to: Vector2D,
52+
level: Int,
53+
): Int {
54+
val config = Triple(from, to, level)
55+
return when {
56+
level == 3 -> 1
57+
config in bestCache -> bestCache[config]!!
58+
from == to -> 1
59+
else -> {
60+
val delta = to - from
61+
val basePath = buildList {
62+
when {
63+
delta.x > 0 -> repeat(delta.x) { add(Directions.R) }
64+
delta.x < 0 -> repeat(-delta.x) { add(Directions.L) }
65+
}
66+
when {
67+
delta.y > 0 -> repeat(delta.y) { add(Directions.D) }
68+
delta.y < 0 -> repeat(-delta.y) { add(Directions.U) }
69+
}
70+
}
71+
72+
val best = basePath.permutations()
73+
.filter { path ->
74+
path.scan(from) { curr, dir -> curr + dir.step }.none { matrix[it] == ' ' }
75+
}
76+
.minOf { path ->
77+
val chars = buildList {
78+
add('A')
79+
path.forEach {
80+
when (it) {
81+
Directions.L -> add('<')
82+
Directions.R -> add('>')
83+
Directions.U -> add('^')
84+
Directions.D -> add('v')
85+
else -> Unit
86+
}
87+
}
88+
add('A')
89+
}
90+
91+
chars.zipWithNext().sumOf { (fromChar, toChar) ->
92+
val fromPoint = handler.find(fromChar)!!
93+
val toPoint = handler.find(toChar)!!
94+
bestPath(handler, handler, fromPoint, toPoint, level + 1)
95+
}
96+
}
97+
98+
bestCache[config] = best
99+
best
100+
}
101+
}
102+
}
103+
}
104+
105+
fun main() = SomeDay.mainify(Day21)

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy