This commit is contained in:
Natsu Kagami 2023-12-21 18:21:38 +01:00
parent 9269c6f2b2
commit cc3e84d95e
Signed by: nki
GPG key ID: 55A032EB38B49ADB
3 changed files with 327 additions and 0 deletions

194
Day21.scala Normal file
View file

@ -0,0 +1,194 @@
package aoc.day21
import aoc._
import aoc.direction._
import scala.collection.mutable
val board =
lines
.map(_.toArray)
.toArray
val startPoint =
board.toSeq.zipWithIndex.findMap { (row, idx) =>
row.toSeq.zipWithIndex.findMap: (cell, col) =>
if cell == 'S' then Some((idx, col)) else None
}.get
def inside(x: Int, y: Int) =
x >= 0 && x < board.length && y >= 0 && y < board(0).length
def walkable(x: Int, y: Int) = inside(x, y) && board(x)(y) != '#'
def getInf(x: Int, y: Int) =
def mod(x: Int, m: Int): Int = if x < 0 then mod(x % m + m, m) else x % m
board(mod(x, board.size))(mod(y, board(0).size))
def walkableInf(x: Int, y: Int) = getInf(x, y) != '#'
// part 1
def walk(steps: Int, starting: Set[(Int, Int)]): Set[(Int, Int)] =
if steps == 0 then starting
else
// println(s"$steps => ${starting.size}")
val ns =
starting
.flatMap((a, b) => Dir.all.map(_(a, b)))
.filter(walkableInf(_, _))
walk(steps - 1, ns)
def part1 =
val possible = walk(300, Set(startPoint))
println(possible.size)
// part 2
object shortestPathsFrom:
val cache = mutable.Map.empty[(Int, Int), Array[Array[Int]]]
def apply(x: Int, y: Int) =
cache.getOrElseUpdate(
(x, y), {
val mp = mutable.Map((x, y) -> 0)
val queue = mutable.Queue((x, y))
while !queue.isEmpty do
val (x, y) = queue.dequeue()
val dist = mp((x, y))
Dir.all
.map(_(x, y))
.filter(walkable(_, _))
.foreach { pt =>
if !mp.contains(pt) then
mp += pt -> (dist + 1)
queue += pt
}
val (a, b) = mp.toMap.partition((_, dist) => dist % 2 == 0)
Iterator(a, b)
.map(v => v.values.toSeq.sorted.toArray)
.toArray
}
)
// input is funni
val _ =
assert(board.head.forall(_ == '.'))
assert(board.last.forall(_ == '.'))
assert(board.forall(_.head == '.'))
assert(board.forall(_.last == '.'))
val (x, y) = startPoint
assert((0 until board.length).forall(board(_)(y) != '#'))
assert((0 until board(0).length).forall(board(x)(_) != '#'))
def pointsReachable(steps: Int): Long =
val (sx, sy) = startPoint
def distToRow(delta: Int) =
if delta == 0 then 0L
else if delta < 0 then
// go up
1L + sx + (delta + 1L).abs * board.size
else 0L + (board.size - sx) + (delta - 1L) * board.size
def distToCol(delta: Int) =
if delta == 0 then 0L
else if delta < 0 then
// go left
1L + sy + (delta + 1L).abs * board(0).size
else 0L + (board(0).size - sy) + (delta - 1L) * board(0).size
def startWhere(dx: Int, dy: Int) =
val x = if dx == 0 then sx else if dx < 0 then board.size - 1 else 0
val y = if dy == 0 then sy else if dy < 0 then board(0).size - 1 else 0
(x, y)
def countWhere(steps: Int, dx: Int, dy: Int) =
val dToBoard = distToRow(dx) + distToCol(dy)
if dToBoard > steps then 0L
else
val (stx, sty) = startWhere(dx, dy)
val dists = shortestPathsFrom(stx, sty)((steps - dToBoard).toInt % 2)
val res = dists.sortedCountUntil(steps - dToBoard.toInt).toLong
// println(s"got $dx $dy $dToBoard $stx $sty => $res ${shortestPathsFrom(stx, sty).map(_.size).toSeq}")
res
(-1 to 1).zip((-1 to 1)).foreach { (dx, dy) =>
val (stx, sty) = startWhere(dx, dy)
// println(s"$dx $dy ${shortestPathsFrom(stx, sty).map(_.size).toSeq}")
}
extension (arr: Array[Int])
def sortedCountUntil(max: Int) =
var low = 0
var hi = arr.size
while low < hi do
val mid = (low + hi) / 2
// println(s"$mid => ${arr(mid)} ~ $max")
if arr(mid) <= max then low = mid + 1 else hi = mid
// println(s"found $low => ${arr(low - 1)}")
low
((0 to steps).toIterator
.takeWhile(distToRow(_) <= steps)
++ (-1 to -steps by -1).toIterator.takeWhile(distToRow(_) <= steps))
.map(dx =>
val dRow = distToRow(dx)
val zero = countWhere(steps, dx, 0)
val right =
val (stx, sty) = startWhere(dx, 1)
val baseDistance = dRow + distToCol(1) // dToBoard = baseDistance + (delta-1) * board.size
if baseDistance > steps then 0L
else
val maxRightAllBoard =
((steps - baseDistance - shortestPathsFrom(stx, sty).map(_.last).max) / board.size).toInt.max(0) + 1
val odd = ((steps - baseDistance) % 2).toInt
val a = (1L until maxRightAllBoard by 2).size * shortestPathsFrom(stx, sty)(odd).size
val b = (2L until maxRightAllBoard by 2).size * shortestPathsFrom(stx, sty)((board.size + odd) % 2).size
// println(
// s"$dx => $maxRightAllBoard [${distToRow(dx) + distToCol(maxRightAllBoard)} ${shortestPathsFrom(stx, sty)
// .map(_.last)
// .max}] ${a + b}"
// )
val rest = (maxRightAllBoard to steps).toIterator
.takeWhile(dRow + distToCol(_) <= steps)
.map(countWhere(steps, dx, _))
.sum
a + b + rest
val left =
val (stx, sty) = startWhere(dx, -1)
val baseDistance = dRow + distToCol(-1) // dToBoard = baseDistance + (delta-1) * board.size
if baseDistance > steps then 0L
else
val maxLeftAllBoard =
((steps - baseDistance - shortestPathsFrom(stx, sty).map(_.last).max) / board.size).toInt.max(0) + 1
// println(s"$dx => -$maxLeftAllBoard")
val odd = ((steps - baseDistance) % 2).toInt
val a = (-1L until -maxLeftAllBoard by -2).size * shortestPathsFrom(stx, sty)(odd).size
val b = (-2L until -maxLeftAllBoard by -2).size * shortestPathsFrom(stx, sty)((board.size + odd) % 2).size
// println(s"$dx => -$maxLeftAllBoard [${distToRow(dx) + distToCol(-maxLeftAllBoard)}] ${a + b}")
val rest = (-maxLeftAllBoard to -steps by -1).toIterator
.takeWhile(dRow + distToCol(_) <= steps)
.map(countWhere(steps, dx, _))
.sum
a + b + rest
zero + right + left
)
.sum
def part2 =
val inputs = Seq(26501365)
// val inputs = Seq(1, 131)
println(inputs.map(pointsReachable))
// val s = walk(200, Set(startPoint))
// // divide by quadrant
// val quads = s.toSeq
// .groupBy((x, y) =>
// val qx = if x < 0 then -(-x + board.size - 1) / board.size else x / board.size
// val qy = if y < 0 then -(-y + board(0).size - 1) / board(0).size else y / board(0).size
// (qx, qy)
// )
// .mapValues(_.size)
// println((quads.toSeq, quads.values.sum))
@main def Day21(part: Int) = part match
case 1 => part1
case 2 => part2

View file

@ -5,6 +5,8 @@ import aoc._
object Dir:
val dx = Array(-1, 0, 1, 0)
val dy = Array(0, 1, 0, -1)
val all = Array(Up, Right, Down, Left)
import Dir._
enum Dir:
case Up, Right, Down, Left

131
inputs/day21.input Normal file
View file

@ -0,0 +1,131 @@
...................................................................................................................................
.#.........#......#................#...#.......#.....##............................##..#........#.#.#.#......#......#...#........#.
..............#..#.....#.....##....................#....................................#....##.#.......#.......#...#...........#..
.#..#..#.#...#.....#.......#......#..#..#.............#.#..................#.......#.............#..#.......#.......#..............
.....................#.............#............#.#................................#.......#........#...............#....#..#......
.....#...........#.......#..................................................#..............#.##.....#..............................
...#.........................##...#.#................#.....................................#.......#.#........#....#.......#....#..
.#....####..........#......................#........#..................................#...........#..#..#....#......#.............
...#.....................#........................#...............................#.......................#....#......#............
....#......#....#......#....#....##..........................#.....#................#.....#........#.....##........................
................#.#....#.#..#....................#..............#........................#...#.......#.#..........#.......#.#......
.........#.#.......#............#.............#...........................................#...#.....#.......................#......
.....#.................#.........#.#.....................#............#..........#.#.#......#...........#.#..............#...#.....
..............................#......#.......#..#..............#....................#...#.##..##..........#...............#...##...
.....#........#.#............#.......#.....###...........................#.....................#................................#..
..##..........#......#...#..............#.....#................#.........#.#...............#...............#.......................
............................#...#.#..................#....................#.......................#.......#........#..#....#....#..
...#............#..#......#...........#................#.....#............................##...##........#..............##.........
..#...#............................#...#...............................#..#..............................#.............#..#....#...
.#.............#...#.....#.#..........#.............#......#..........#....#.#.................#.................#..#......##..#...
.......#........#..................#.....#........#.#.........#........##....#..............#.......#...#....#.............#.......
.........#.........#......#.#..#....#............##......#...........#.....................#.....#.#.....#.................#.......
..............................#.#......#............#..#....#....................##.............#...##....#.................###....
......#...##...#....#.##...........#.#...........#...##..............#.#.....##....#..........#..#.........#.....#.................
....##...###.........................#............#............#.............#.##...............#..............##.....#............
.....#..#......##.#.........#.....##............#.....#.........#...................#......................#........#..........###.
............#.............#........#.......#...###......#...#.#......##.#...........#..#......................#................#...
..........................................................#........................#..........................#....#....##.....#...
....#...#........#.......................#..........#.............#..#.#...............................#.......##.#...##...........
...#........#..........#........................#...........#.............#.#.....................#...#.#.##.#..................#..
.......................#....#..............#..####......##.#.............#...........#...##............#..#..........##...#.....#..
..#.................#.#..................#.#.....#...#.#..##...#.........#.................#.............#....#..#.......#.........
..#............#..#.....................#.................#............#.....##.#..#.#................#....................#...#...
..#.###.##.......................................##.............#..#...#...........#...#....#...........###......#............#....
........#....#.......#.....................#...................................#...#.#.....#..............................#....#...
.#..#........#...#.....#.............##..#....#................#................................#.........#....#..............#....
............#..........#............#...#.......#..#.#.#.......#....#...........#...#....#............................#.#..........
............................................................#..................#..............#...............................#....
.........#.....#......##........#......#.##..##............##.......................#.........................#....#...............
.#...#...#.#..#...#..............................#...................#..#....................##..........................#.##......
.............#...#...........#......#..#..##...#......#....##.....#................##.........#...........................#........
.................#..................#.........#....#...#..................##............#..#...#.................#..#...........#..
...#...#..........#.........#.....#.........................#.#................#......##...............#............#......#....##.
.............#.................#.............#..#...#.............#.........#..#.#..#............##.............#...#..............
......#.#........#........#...........#..##...................##....#.....................#..#.........#..........#.....##.....#.#.
...........#.#.............#.......#....#..........#.#...............#.#...##.............................................#........
...............#........................#.....#.......#................#........#.......#.....#.......................##...........
......................................#...............................#..........#................#........#.......................
.............................#....#.....##.....#....#...#...........#....#.......##..#.................................#...........
............#.............#......#..#.#.##............#.............#.......#....................#....##...........................
..........#...........#..#.......#.........#.............#...................#.#..#..#....#........#...#...........................
.....................#........#............#.........#.........#..................#...#.........#..............#........#......#...
.................#.............#.#.#.#....#...#..#...................................................#......#......................
........#........#....................#...##....#.#...#..#..#.......#.....#.....#....#.............................................
...#...................#.....#...................#......................#............#......#....#.#.........#.#...................
.#.......................#...#.....#.#....................#.......#............#............#........#.............................
...............#..#..#..............#...#..#...............#.##..................#.......#...........#....#....#...#..........#....
...............#................................#..#............#....#....#.............#...............##..#......#............#..
.........................#..............#.#..#....................#.#.#.....#...............#........#.##.#.......#................
.#...........#.##..#...#.#...........#.......#...............................####....................##....#.........#.#...........
...................#...........#........#..#.........#............#..........#.........#...#.......................................
..............#..#...#..#..#.##............#..#..#.............##.##.#..#.......................#..........#..........#..#.........
........##...............##..#..#...........#.............#.#.................#..........#........................#.#...#..........
..............#......#........#........#.#.........#..#.....#.....#..#...##...................#..........#.............#...........
.................#.......#....#.....................#....##...............##....................#......#....#..........#..#.#......
.................................................................S.................................................................
.........#..##...#..#.........#.................................#.........#....#.#............#..#........#.......#.......#........
...................#....#..#....#...#......#....#......#...........................#.............###...............#......#........
...........#...............#........................#.#......#.#............#...#.#.................#....#...#...#.................
..................#...................#..#.........#...##..#...#...................#...#.....#.....#....#.......#.#................
...............#..............#........#................................................#...#.#......#.#.........#....#............
...............##.........#.....#....#................#.....#.#................#.......#................#..........................
...........#.............#...#...................##................#.......#....#...#...........#.#................................
.................#..............................#.....................#.....#...............#...#...................#..............
..............................#.................#..........#............#.......#..............#.#.................................
...............#..............#....#............#......#...#.........#.......##............##...#..#..........................##...
..........................#.#...........#....#.........##..............##......#.........................#.....#................#..
........#...................#..#...#.......................#..................#.#.............#..#.............#...........#.......
.............................#............#....#.....................#.....#..........#..##.............#.#......#.......#.........
....#.........................................#......##...#...........................##........#...#.#............................
.....#.....................#..#....##..#..........#........................##.....#..........#................#....................
.......................................#..#......#.#..##.....#...........#..#.......#.................#...#.................##..##.
....#.....#............#...#......#..............#...................#...........#.........#.........................#....##..##...
......#....#.................#.............#....#..#.....#........#.#........#.....#.#.#.#..#......................................
.........#..........................................#..............##.......#........#...#..#............#.#.............#.#...#...
............#............#.....#..#............#..#.....#.....#....#....#..#............#................#..............#......#...
.###.........#....................................#.#..#......#...#.....#.......#..#.....#.....##.....##.............#....#.#......
..###.......................#.......#..#..........#.............................#...............#..#..#.............##.......#.....
.#.......#...........................................#..#.................#........#.#...............#.....................#.......
.......#....#.....##...........#..#.............#........#..................#.......#.......#.........#......................#.....
.......#...#......#................#..#.#..........#.....................................##....#.............#......#..........##..
.....###.#....#.#..................#........##.#........#...#..............#...........#......#.......................#....#.....#.
.#...........................................................#.#.......#..........#.#.......................#.......#.#......#.....
.....#.................................#....#...#.#.#....#...#....#....#....#.....##....#.............................#.#..#.......
.............#..#........#...........#.....#.......#..#....#..#...#.......................#....#...........#...............#.......
...##...#.##.....#............................#.....##.........................#..#.#...........#.............#........#...........
.........#..#........#..#..................#....#.#........#....#....##....#...........#...#............................#..#.......
..#....#..#.#......#.......#..............#.#............................#............#.................#.......#...###.....#.#.#..
..#.......#.........###....#.........#........##....#......................#...........................#.....##.........#...#......
.##.............#.........#...........#..................................#.....#....#....#.##...............#......#...............
.....#...........#...#......#..........#..................#..#..#.......................#..........................................
.....#..................#..#..#............#..#...........#..#.......#........##...#..................#............................
.....................#.......#...........#..........##........#...............#.#..#...................#........#..#....#..........
.#.........#..#................#............#......#.......#.......#.....#..#.#.#..##..#..........#....##..#.......................
..................##..##..................................#................#.........#...........#....#.........#..#.#.............
.....#..#..............#......#................................#...........#...#...#............##...........................#.....
...#................##.........#.#...#............................#.#....#.#....#...#.........#.......#............#....#.#..#..#..
.................#.......#.#......#.#............##........#................................#....#..#..............................
...#................#................................#.##.#.##.......#...........#....................#......#.....................
.#.........#....#..........##........#.#..........#.#......#..#............##....#................#.......#.............#..........
.................#....#..........#..................#........#.#..........#...............#.....#..#..............#............#.#.
...#..#.......#.......................#...........##.................#....#.....#............#........##.............#.....#..#....
....#.............##............#...#..#....................#.......#.........#..............................#.....................
...#......................#.................#.............#............................#....#.............#......#...#.............
...#.........#........................................#..#.....##......#....##.......#..#........#...#..#.....#.#.............#..#.
..#.......#..................#..#.....#.....#.#.........#.....#......................#....##...............#..........#.....#......
..................#..##........#....#...................#.......#..................#..#.......##...................................
.....#..#.#.#.#.....#........#.....................................#......#..........##........................#......#...#..#.....
...#.#.........##....#..#...................#............#.....##.............................##.........#.....#.............#.....
.#....#................#..........................................#............................#........#...##................#.#..
.........#..........##...#........##.#....#.....#............#.....#..............#....#.#..#............##....#.....#.......##....
.............##......#.................#........#..##...............#..........................#....#.......##........#........##..
......#.....##.......#....................#..........#.........................#...#.......#...##..#..............#........#.......
..#..........#......#....#..............#.......................#...........#.....#................#....#.#.#...#.........#........
.....##.#.#..#.#..............................#...#..##..........................#.#..............###.#............................
.........#.....#...##.............#.........#.....#..........................#.....................................#..#..........#.
.#..##........................#........#............#..........................................#..#..........#.....#..#.....#...#..
.............#..............#.##..............#........#..................##........#.........##.......#.#.....#..#......#..#.#....
..........#....#.###...#........#..#......................................#......#..............#..............#...................
...........#..................#...........#..............................#....................#..#.................#...............
...................................................................................................................................