Day 6
This commit is contained in:
parent
5dde3b6445
commit
ba564dc7e1
10 changed files with 66 additions and 15 deletions
|
@ -4,6 +4,7 @@ import cats._
|
|||
import cats.effect._
|
||||
import fs2._
|
||||
|
||||
trait Day:
|
||||
trait Day {
|
||||
def part1[F[_]: Async]: Pipe[F, String, String]
|
||||
def part2[F[_]: Async]: Pipe[F, String, String]
|
||||
}
|
||||
|
|
|
@ -7,13 +7,13 @@ import cats.syntax.all._
|
|||
import java.nio.charset.StandardCharsets
|
||||
import fs2._
|
||||
|
||||
object Main extends IOApp:
|
||||
object Main extends IOApp {
|
||||
|
||||
def years: Map[Int, Year] = Map(
|
||||
2020 -> y2020.y2020,
|
||||
)
|
||||
|
||||
override def run(args: List[String]): IO[ExitCode] =
|
||||
override def run(args: List[String]): IO[ExitCode] = {
|
||||
val year: IO[Year] = selectYear[IO]
|
||||
val day: IO[Day] = year >>= selectDay[IO]
|
||||
val part: IO[Pipe[IO, String, String]] = day >>= selectPart[IO]
|
||||
|
@ -24,8 +24,9 @@ object Main extends IOApp:
|
|||
.through(io.stdoutLines(StandardCharsets.UTF_8))
|
||||
.compile.drain
|
||||
}.as(ExitCode.Success)
|
||||
}
|
||||
|
||||
def selectYear[F[_]: Monad: Console]: F[Year] =
|
||||
def selectYear[F[_]: Monad: Console]: F[Year] = {
|
||||
val ask = Console[F].print("Select year: ")
|
||||
val receive = Console[F].readLine
|
||||
val year: F[Option[Year]] = (ask >> receive).map(_.toIntOption >>= years.get)
|
||||
|
@ -33,8 +34,9 @@ object Main extends IOApp:
|
|||
case Some(year) => year.pure[F]
|
||||
case None => selectYear[F]
|
||||
}
|
||||
}
|
||||
|
||||
def selectDay[F[_]: Monad: Console](year: Year): F[Day] =
|
||||
def selectDay[F[_]: Monad: Console](year: Year): F[Day] = {
|
||||
val ask = Console[F].print("Select day: ")
|
||||
val receive = Console[F].readLine
|
||||
val day: F[Option[Day]] = (ask >> receive).map(_.toIntOption >>= year.days.get)
|
||||
|
@ -42,8 +44,9 @@ object Main extends IOApp:
|
|||
case Some(day) => day.pure[F]
|
||||
case None => selectDay[F](year)
|
||||
}
|
||||
}
|
||||
|
||||
def selectPart[F[_]: Async: Console](day: Day): F[Pipe[F, String, String]] =
|
||||
def selectPart[F[_]: Async: Console](day: Day): F[Pipe[F, String, String]] = {
|
||||
val ask = Console[F].print("Select part: ")
|
||||
val receive = Console[F].readLine
|
||||
val part: F[Option[Int]] = (ask >> receive).map(_.toIntOption)
|
||||
|
@ -52,3 +55,6 @@ object Main extends IOApp:
|
|||
case Some(2) => day.part2[F].pure[F]
|
||||
case _ => selectPart[F](day)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
package tf.bug.aoc
|
||||
|
||||
trait Year:
|
||||
trait Year {
|
||||
def days: Map[Int, Day]
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ import java.nio.charset.StandardCharsets
|
|||
import scala.util.Try
|
||||
import tf.bug.aoc.Day
|
||||
|
||||
object Day1 extends Day:
|
||||
object Day1 extends Day {
|
||||
|
||||
override def part1[F[_]: Async]: Pipe[F, String, String] =
|
||||
parts[F](2)
|
||||
|
@ -29,3 +29,5 @@ object Day1 extends Day:
|
|||
ints.combinations(num).collectFirst {
|
||||
case v if v.sum == target => v.product
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ import cats.syntax.all._
|
|||
import fs2._
|
||||
import tf.bug.aoc.Day
|
||||
|
||||
object Day2 extends Day:
|
||||
object Day2 extends Day {
|
||||
|
||||
case class Policy(min: Int, max: Int, letter: Char)
|
||||
case class Entry(policy: Policy, password: String)
|
||||
|
@ -45,3 +45,5 @@ object Day2 extends Day:
|
|||
.foldMap(ent => if(validation(ent)) 1 else 0)
|
||||
.map(_.show)
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ import cats.syntax.all._
|
|||
import fs2._
|
||||
import tf.bug.aoc.Day
|
||||
|
||||
object Day3 extends Day:
|
||||
object Day3 extends Day {
|
||||
|
||||
case class Path(x: Int, treeCount: Long)
|
||||
|
||||
|
@ -44,3 +44,5 @@ object Day3 extends Day:
|
|||
}
|
||||
}.map(_.treeCount)
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ import cats.syntax.all._
|
|||
import fs2._
|
||||
import tf.bug.aoc.Day
|
||||
|
||||
object Day4 extends Day:
|
||||
object Day4 extends Day {
|
||||
|
||||
val whitespace: Parser1[Unit] = P.charIn(" ").void
|
||||
|
||||
|
@ -17,7 +17,7 @@ object Day4 extends Day:
|
|||
|
||||
val parseMap: P[Map[String, String]] = (P.repSep(parseEntry, min = 0, sep = whitespace) <* P.until(P.end)).map(_.toMap)
|
||||
|
||||
override def part1[F[_]: Async]: Pipe[F, String, String] =
|
||||
override def part1[F[_]: Async]: Pipe[F, String, String] = {
|
||||
val requiredKeys = Set(
|
||||
"byr", "iyr", "eyr", "hgt", "hcl", "ecl", "pid"
|
||||
)
|
||||
|
@ -25,8 +25,9 @@ object Day4 extends Day:
|
|||
val keySet = m.keySet
|
||||
requiredKeys.forall(keySet.contains)
|
||||
}
|
||||
}
|
||||
|
||||
override def part2[F[_]: Async]: Pipe[F, String, String] =
|
||||
override def part2[F[_]: Async]: Pipe[F, String, String] = {
|
||||
val hexChar: P[Unit] = P.charIn(('0' to '9') ++ ('a' to 'f')).void
|
||||
val validateColor: P[Unit] = P.char('#') *> hexChar.replicateA(6).void
|
||||
val eyeColors: Set[String] = Set(
|
||||
|
@ -56,6 +57,7 @@ object Day4 extends Day:
|
|||
lazy val validPid = m.get("pid").fold(false)(validatePid.parseAll(_).isRight)
|
||||
validByr && validIyr && validEyr && validHgt && validHcl && validEcl && validPid
|
||||
}
|
||||
}
|
||||
|
||||
def parts[F[_]: Async](validator: Map[String, String] => Boolean): Pipe[F, String, String] =
|
||||
(lines: Stream[F, String]) => {
|
||||
|
@ -70,3 +72,5 @@ object Day4 extends Day:
|
|||
.foldMap(if(_) 1 else 0)
|
||||
.map(_.show)
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ import fs2._
|
|||
import scala.collection.SortedSet
|
||||
import tf.bug.aoc.Day
|
||||
|
||||
object Day5 extends Day:
|
||||
object Day5 extends Day {
|
||||
|
||||
override def part1[F[_]: Async]: Pipe[F, String, String] =
|
||||
(lines: Stream[F, String]) => {
|
||||
|
@ -44,3 +44,5 @@ object Day5 extends Day:
|
|||
val newBit = ((ch & 4) >>> 2) ^ 1
|
||||
(id * 2) + newBit
|
||||
})
|
||||
|
||||
}
|
||||
|
|
27
core/src/main/scala/tf/bug/aoc/y2020/Day6.scala
Normal file
27
core/src/main/scala/tf/bug/aoc/y2020/Day6.scala
Normal file
|
@ -0,0 +1,27 @@
|
|||
package tf.bug.aoc.y2020
|
||||
|
||||
import cats.effect._
|
||||
import cats.syntax.all._
|
||||
import fs2._
|
||||
import tf.bug.aoc.Day
|
||||
|
||||
object Day6 extends Day {
|
||||
|
||||
override def part1[F[_]: Async]: Pipe[F, String, String] =
|
||||
parts(_ | _)
|
||||
|
||||
override def part2[F[_]: Async]: Pipe[F, String, String] =
|
||||
parts(_ & _)
|
||||
|
||||
def parts[F[_]: Async](reduction: (Set[Char], Set[Char]) => Set[Char]): Pipe[F, String, String] =
|
||||
(lines: Stream[F, String]) => {
|
||||
lines.groupAdjacentBy(_.nonEmpty).collect {
|
||||
case (true, strings) =>
|
||||
strings
|
||||
.map(_.toSet)
|
||||
.reduceLeftOption(reduction)
|
||||
.getOrElse(Set.empty[Char])
|
||||
}.map(_.size).foldMonoid.map(_.show)
|
||||
}
|
||||
|
||||
}
|
|
@ -2,11 +2,15 @@ package tf.bug.aoc.y2020
|
|||
|
||||
import tf.bug.aoc.{Day, Year}
|
||||
|
||||
object y2020 extends Year:
|
||||
object y2020 extends Year {
|
||||
|
||||
override def days: Map[Int, Day] = Map(
|
||||
1 -> Day1,
|
||||
2 -> Day2,
|
||||
3 -> Day3,
|
||||
4 -> Day4,
|
||||
5 -> Day5,
|
||||
6 -> Day6,
|
||||
)
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue