Day 14
This commit is contained in:
parent
d5e1e549d6
commit
86c4da24ee
2 changed files with 223 additions and 0 deletions
123
src/day14.scala
Normal file
123
src/day14.scala
Normal file
|
|
@ -0,0 +1,123 @@
|
|||
package aoc
|
||||
package day14
|
||||
|
||||
import scala.annotation.tailrec
|
||||
import scala.collection.mutable
|
||||
|
||||
val dayNumber = "14"
|
||||
|
||||
@main def part1: Unit =
|
||||
println(part1(loadInput(dayNumber)))
|
||||
|
||||
@main def part2: Unit =
|
||||
println(part2(loadInput(dayNumber)))
|
||||
|
||||
def part1(input: String): String =
|
||||
val lines = input.split('\n')
|
||||
val border = lines.head.map(_ => '#').mkString + "##"
|
||||
val grid = lines
|
||||
.map(l => s"#$l#")
|
||||
.prepended(border)
|
||||
.appended(border)
|
||||
.map(_.to(mutable.ArraySeq))
|
||||
for
|
||||
y <- grid.indices
|
||||
x <- grid.head.indices
|
||||
do
|
||||
if grid(y)(x) != 'O' then ()
|
||||
else
|
||||
(y - 1 to (0, -1))
|
||||
.takeWhile(grid(_)(x) == '.')
|
||||
.lastOption
|
||||
.foreach(newY =>
|
||||
grid(y)(x) = '.'
|
||||
grid(newY)(x) = 'O'
|
||||
)
|
||||
|
||||
grid
|
||||
.map(_.count(_ == 'O'))
|
||||
.reverse
|
||||
.zipWithIndex
|
||||
.map((count, row) => count * row)
|
||||
.sum
|
||||
.toString
|
||||
|
||||
def part2(input: String): String =
|
||||
val lines = input.split('\n')
|
||||
val border = lines.head.map(_ => '#').mkString + "##"
|
||||
val grid = lines
|
||||
.map(l => s"#$l#")
|
||||
.prepended(border)
|
||||
.appended(border)
|
||||
.map(_.to(mutable.ArraySeq))
|
||||
|
||||
val coords =
|
||||
for
|
||||
y <- grid.indices
|
||||
x <- grid.head.indices
|
||||
yield (x, y)
|
||||
|
||||
enum Directions(
|
||||
val coordinates: Seq[(Int, Int)],
|
||||
val rangeToEdge: (Int, Int) => Seq[(Int, Int)]
|
||||
):
|
||||
case North
|
||||
extends Directions(
|
||||
coords,
|
||||
(x, y) => (y - 1 to (0, -1)).map((x, _))
|
||||
)
|
||||
case West
|
||||
extends Directions(
|
||||
coords.sortBy(_._1),
|
||||
(x, y) => (x - 1 to (0, -1)).map((_, y))
|
||||
)
|
||||
case South
|
||||
extends Directions(
|
||||
coords.reverse,
|
||||
(x, y) => (y + 1 until grid.length).map((x, _))
|
||||
)
|
||||
case East
|
||||
extends Directions(
|
||||
coords.sortBy(_._1).reverse,
|
||||
(x, y) => (x + 1 until grid.length).map((_, y))
|
||||
)
|
||||
|
||||
def cycle =
|
||||
for d <- Directions.values do
|
||||
for (x, y) <- d.coordinates do
|
||||
if grid(y)(x) != 'O' then ()
|
||||
else
|
||||
d.rangeToEdge(x, y)
|
||||
.takeWhile((xR, yR) => grid(yR)(xR) == '.')
|
||||
.lastOption
|
||||
.foreach((xR, yR) =>
|
||||
grid(y)(x) = '.'
|
||||
grid(yR)(xR) = 'O'
|
||||
)
|
||||
|
||||
def cycleUntilRepeat: (Int, Int) =
|
||||
val seen = mutable.Map.empty[String, Int]
|
||||
|
||||
@tailrec def aux(iter: Int): (Int, Int) =
|
||||
cycle
|
||||
val gridString = grid.map(_.mkString).mkString("\n")
|
||||
seen.get(gridString) match
|
||||
case Some(prevIterations) => (iter, iter - prevIterations)
|
||||
case None =>
|
||||
seen.put(gridString, iter)
|
||||
aux(iter + 1)
|
||||
|
||||
aux(1)
|
||||
|
||||
val (repeatedIndex, repeatedLength) = cycleUntilRepeat
|
||||
val cyclesLeft = (1_000_000_000 - repeatedIndex) % repeatedLength
|
||||
|
||||
for _ <- (0 until cyclesLeft) do cycle
|
||||
|
||||
grid
|
||||
.map(_.count(_ == 'O'))
|
||||
.reverse
|
||||
.zipWithIndex
|
||||
.map((count, row) => count * (row))
|
||||
.sum
|
||||
.toString
|
||||
Loading…
Add table
Add a link
Reference in a new issue