Compare commits
2 Commits
cdf14fdada
...
6db15ba9af
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6db15ba9af | ||
|
|
58710aca7a |
@@ -22,7 +22,8 @@ val solvers = Map[Int, Solver](
|
|||||||
17 -> Day17,
|
17 -> Day17,
|
||||||
18 -> Day18,
|
18 -> Day18,
|
||||||
19 -> Day19,
|
19 -> Day19,
|
||||||
20 -> Day20
|
20 -> Day20,
|
||||||
|
21 -> Day21
|
||||||
)
|
)
|
||||||
|
|
||||||
def runSolver(solver: Solver, input: os.Path): Unit =
|
def runSolver(solver: Solver, input: os.Path): Unit =
|
||||||
|
|||||||
@@ -20,11 +20,11 @@ object Day20 extends Solver(20):
|
|||||||
|
|
||||||
def cheats(radius: Int): Int =
|
def cheats(radius: Int): Int =
|
||||||
trace.indices.par
|
trace.indices.par
|
||||||
.map(a =>
|
.map(toDist =>
|
||||||
(a + 1 until trace.length)
|
(toDist + 100 until trace.length)
|
||||||
.count(b =>
|
.count(fromDist =>
|
||||||
val (from, fromDist) = (trace(a), trace.length - a)
|
val from = trace(toDist)
|
||||||
val (to, toDist) = (trace(b), trace.length - b)
|
val to = trace(fromDist)
|
||||||
val dist = (from - to).manhattan
|
val dist = (from - to).manhattan
|
||||||
|
|
||||||
dist <= radius && (fromDist - toDist >= 100 + dist)
|
dist <= radius && (fromDist - toDist >= 100 + dist)
|
||||||
|
|||||||
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