diff --git a/core/src/main/scala/tf/bug/aoc/y2020/Day5.scala b/core/src/main/scala/tf/bug/aoc/y2020/Day5.scala index 71b32a9..5f67997 100644 --- a/core/src/main/scala/tf/bug/aoc/y2020/Day5.scala +++ b/core/src/main/scala/tf/bug/aoc/y2020/Day5.scala @@ -8,55 +8,39 @@ import tf.bug.aoc.Day object Day5 extends Day: - case class Seat(row: Int, col: Int) { - def id = row * 8 + col - } - - object Seat { - implicit val seatOrdering: Ordering[Seat] = Ordering.by(_.id) - } - override def part1[F[_]: Async]: Pipe[F, String, String] = (lines: Stream[F, String]) => { lines.through(seats[F]) - .map(_.id) .fold1(_.max(_)) .map(_.show) } + case class SearchState(min: Int, max: Int, sum: Int) + override def part2[F[_]: Async]: Pipe[F, String, String] = (lines: Stream[F, String]) => { - val sortedSeats: F[SortedSet[Seat]] = - lines.through(seats[F]) - .compile.to(Collector.supportsFactory(SortedSet)) - val pairs: Stream[F, (Seat, Seat)] = - Stream.eval(sortedSeats) - .flatMap(seats => Stream.fromIterator[F](seats.sliding(2).map(set => (set.min, set.max)), 1)) - val gaps: Stream[F, Int] = pairs.collect { - case (a, b) if a.id + 1 == b.id - 1 => a.id + 1 - } - gaps.map(_.show) + lines + .filter(_.nonEmpty) + .through(seats[F]) + .fold(SearchState(Int.MaxValue, Int.MinValue, 0)) { + case (SearchState(min, max, sum), seat) => + val newMin = seat.min(min) + val newMax = seat.max(max) + val newSum = sum + seat + SearchState(newMin, newMax, newSum) + } + .map { + case SearchState(min, max, sum) => + val range = (max - min) + 1 + val total = ((max + min) * range) / 2 + total - sum + } + .map(_.show) } - def seats[F[_]: Async]: Pipe[F, String, Seat] = - (lines: Stream[F, String]) => { - lines - .map { s => - val (row, col) = s.splitAt(7) - val rowN = row.zipWithIndex.foldLeft(0) { - case (n, ('F', _)) => - n - case (n, ('B', i)) => - val range = 1 << (6 - i) - n + range - } - val colN = col.zipWithIndex.foldLeft(0) { - case (n, ('L', _)) => - n - case (n, ('R', i)) => - val range = 1 << (2 - i) - n + range - } - Seat(rowN, colN) - } - } + def seats[F[_]: Async]: Pipe[F, String, Int] = + _.map(_.foldLeft(0) { + case (id, ch) => + val newBit = ((ch & 4) >>> 2) ^ 1 + (id * 2) + newBit + })