Day 21
This commit is contained in:
@@ -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 =
|
||||
|
||||
48
aoc/src/dev/ctsk/aoc/days/Day21.scala
Normal file
48
aoc/src/dev/ctsk/aoc/days/Day21.scala
Normal 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
2
data/21.ans
Normal file
@@ -0,0 +1,2 @@
|
||||
202274
|
||||
245881705840972
|
||||
5
data/21.in
Normal file
5
data/21.in
Normal file
@@ -0,0 +1,5 @@
|
||||
319A
|
||||
670A
|
||||
349A
|
||||
964A
|
||||
586A
|
||||
Reference in New Issue
Block a user