aoc2023/Day6.scala

49 lines
1.3 KiB
Scala
Raw Normal View History

2023-12-06 09:27:15 +00:00
package aoc.day6
import aoc._
case class Race(time: Long, distance: Long):
def waysToWin =
val minTime = search(0, (time - 1) / 2)
val midOk = if time % 2 == 0 && withHold(time / 2) > distance then 1L else 0
2 * (minTime to (time - 1) / 2).length + midOk
@scala.annotation.tailrec
private final def search(min: Long, max: Long): Long =
if min >= max then min
else
val mid = (max + min) / 2
if withHold(mid) <= distance then search(mid + 1, max)
else search(min, mid)
def withHold(k: Long) = k * (time - k)
object Parser extends CommonParser:
val nums = rep1(num)
def time[T](nums: Parser[T]) = "Time:" ~> nums
def distance[T](nums: Parser[T]) = "Distance:" ~> nums
val bigNum = rep1("""\d+""".r) ^^ (_.mkString.toLong)
def races(ss: Seq[String]) = ss match {
case Seq(t, d) =>
parse(time(nums), t).get.zip(parse(distance(nums), d).get).map(Race(_, _))
}
def bigRace(ss: Seq[String]) = ss match {
case Seq(t, d) =>
Race(parse(time(bigNum), t).get, parse(distance(bigNum), d).get)
}
def part1 =
val races = Parser.races(lines.toSeq)
val res = races.map(_.waysToWin).product
println(res)
def part2 =
val race = Parser.bigRace(lines.toSeq)
val res = race.waysToWin
println(res)
@main def Day6(part: Int) = part match
case 1 => part1
case 2 => part2