aoc2023/Day18.scala

70 lines
1.7 KiB
Scala
Raw Permalink Normal View History

2023-12-19 15:12:41 +00:00
package aoc.day18
import aoc._
import aoc.direction._
import Dir._
import scala.collection.SortedMap
import scala.collection.mutable
case class Dig(dir: Dir, count: Int, color: String):
lazy val part2 = Parser.parse(Parser.digHex, color).get
def apply(x: Long, y: Long) = dir.long(x, y, count)
object Parser extends CommonParser with DirParser:
val dig = dir ~ num ~ "(#" ~ """[0-9a-f]{6}""".r ~ ")" ^^ { case dir ~ num ~ _ ~ color ~ _ =>
Dig(dir, num, color)
}
val hexDigit = """[0-9a-f]""".r ^^ {
case c if c.charAt(0).isDigit => c.charAt(0) - '0'
case c => c.charAt(0) - 'a' + 10
}
def hexNum(len: Int) = repN(len, hexDigit).map(_.foldLeft(0)(_ * 16 + _))
val toDir = Array(Right, Down, Left, Up)
val digHex = hexNum(5) ~ hexDigit ^^ { case num ~ dig => Dig(toDir(dig), num, "") }
def apply(s: String) = parse(dig, s).get
def instructions() = lines.map(Parser(_)).toSeq
def points(ins: Seq[Dig]) =
ins
.scanLeft((0L, 0L)) { case ((x, y), in) => in(x, y) }
.dropRight(1)
extension [T](ss: Seq[T]) def shiftLeft = ss.drop(1) ++ ss.take(1)
def area(pts: Seq[(Long, Long)]) = pts
.lazyZip(pts.shiftLeft)
.map { case ((ax, ay), (bx, by)) =>
(bx - ax) * (by + ay)
}
.sum
.abs
def circum(pts: Seq[(Long, Long)]) = pts
.lazyZip(pts.shiftLeft)
.map { case ((ax, ay), (bx, by)) =>
(bx - ax).abs + (by - ay).abs
}
.sum
def areaBlock(pts: Seq[(Long, Long)]) = (area(pts) + circum(pts)) / 2 + 1
def part1 =
val ins = instructions()
val pts = points(ins)
println(areaBlock(pts))
def part2 =
val ins = instructions().map(_.part2)
val pts = points(ins)
println(areaBlock(pts))
@main def Day18(part: Int) = part match
case 1 => part1
case 2 => part2