aoc/core/src/main/scala/tf/bug/aoc/y2020/Day5.scala

63 lines
1.7 KiB
Scala

package tf.bug.aoc.y2020
import cats.effect._
import cats.syntax.all._
import fs2._
import scala.collection.SortedSet
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)
}
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.evidenceIterableFactory[Seat]))
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)
}
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)
}
}