Compare commits

...

2 Commits

Author SHA1 Message Date
Christian
6db15ba9af Day 21 2024-12-21 20:01:19 +01:00
Christian
58710aca7a Day 20 shave off some cycles 2024-12-20 20:52:05 +01:00
5 changed files with 63 additions and 7 deletions

View File

@@ -22,7 +22,8 @@ val solvers = Map[Int, Solver](
17 -> Day17,
18 -> Day18,
19 -> Day19,
20 -> Day20
20 -> Day20,
21 -> Day21
)
def runSolver(solver: Solver, input: os.Path): Unit =

View File

@@ -20,18 +20,18 @@ object Day20 extends Solver(20):
def cheats(radius: Int): Int =
trace.indices.par
.map(a =>
(a + 1 until trace.length)
.count(b =>
val (from, fromDist) = (trace(a), trace.length - a)
val (to, toDist) = (trace(b), trace.length - b)
.map(toDist =>
(toDist + 100 until trace.length)
.count(fromDist =>
val from = trace(toDist)
val to = trace(fromDist)
val dist = (from - to).manhattan
dist <= radius && (fromDist - toDist >= 100 + dist)
)
)
.sum
val p1 = timed { cheats(2) }
val p2 = timed { cheats(20) }

View File

@@ -0,0 +1,48 @@
package dev.ctsk.aoc.days
import dev.ctsk.aoc.*
object Day21 extends Solver(21):
private val keyPad = Grid(Array("789", "456", "123", " 0A").map(_.toArray))
private val buttonPad = Grid(Array(" ^A", "<v>").map(_.toArray))
private val paths = Memo(paths_)
private def paths_(args: (Char, Char, Grid[Char])): Array[Array[Char]] =
val (from, to, grid) = args
val Point(fx, fy) = grid.findFirst(_ == from).get
val Point(tx, ty) = grid.findFirst(_ == to).get
val ops = Seq((fx, tx, 'v'), (tx, fx, '^'), (fy, ty, '>'), (ty, fy, '<'))
val seq = ops.flatMap((a, b, c) => (a until b).map(_ => c))
def gap(path: Array[Char]): Boolean =
path
.scanLeft(Point(fx, fy))((acc, c) => Direction.from(c)(acc))
.exists(grid(_).contains(' '))
seq.permutations.map(_.toArray).filterNot(gap).toArray
private def countPresses(codes: Array[String], numRobots: Int): Long =
type State = (Char, Char, Int)
def minCost_(state: State, f: State => Long): Long =
val (from, to, robots) = state
if robots == 0 then return 1
paths(from, to, if robots == numRobots then keyPad else buttonPad)
.map('A' +: _ :+ 'A')
.map(path => path.sliding(2).map(w => f(w(0), w(1), robots - 1)).sum)
.min
val minCost = Memo.Y(minCost_)
def evalCode(line: String): Long =
('A' +: line).sliding(2).map(w => minCost(w(0), w(1), numRobots)).sum
codes.map(code => code.init.toInt * evalCode(code)).sum
override def run(input: os.ReadablePath): (Timings, Solution) =
val codes = os.read.lines(input).toArray
val (p1_time, p1_solution) = timed { countPresses(codes, 3) }
val (p2_time, p2_solution) = timed { countPresses(codes, 26) }
(
Timings(0, p1_time, p2_time),
Solution(Long.box(p1_solution), Long.box(p2_solution))
)

2
data/21.ans Normal file
View File

@@ -0,0 +1,2 @@
202274
245881705840972

5
data/21.in Normal file
View File

@@ -0,0 +1,5 @@
319A
670A
349A
964A
586A