Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

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)

AltStyle によって変換されたページ (->オリジナル) /