diff --git a/Day5.scala b/Day5.scala index a4ca337..036cb9b 100644 --- a/Day5.scala +++ b/Day5.scala @@ -102,6 +102,7 @@ def toLocation(seed: Long) = loop("seed", seed) def toLocation(seed: LRange) = + @scala.annotation.tailrec def loop(entryName: String, value: Seq[LRange]): Seq[LRange] = if entryName == "location" then value else diff --git a/Day6.scala b/Day6.scala new file mode 100644 index 0000000..98c0cb0 --- /dev/null +++ b/Day6.scala @@ -0,0 +1,48 @@ +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 diff --git a/inputs/day6.input b/inputs/day6.input new file mode 100644 index 0000000..1e7db17 --- /dev/null +++ b/inputs/day6.input @@ -0,0 +1,2 @@ +Time: 56 97 77 93 +Distance: 499 2210 1097 1440