From ba564dc7e134769fbfd2fa0a3bba72cc61337984 Mon Sep 17 00:00:00 2001 From: Aly Date: Sun, 6 Dec 2020 14:39:00 -0800 Subject: [PATCH] Day 6 --- core/src/main/scala/tf/bug/aoc/Day.scala | 3 ++- core/src/main/scala/tf/bug/aoc/Main.scala | 16 +++++++---- core/src/main/scala/tf/bug/aoc/Year.scala | 3 ++- .../main/scala/tf/bug/aoc/y2020/Day1.scala | 4 ++- .../main/scala/tf/bug/aoc/y2020/Day2.scala | 4 ++- .../main/scala/tf/bug/aoc/y2020/Day3.scala | 4 ++- .../main/scala/tf/bug/aoc/y2020/Day4.scala | 10 ++++--- .../main/scala/tf/bug/aoc/y2020/Day5.scala | 4 ++- .../main/scala/tf/bug/aoc/y2020/Day6.scala | 27 +++++++++++++++++++ .../main/scala/tf/bug/aoc/y2020/y2020.scala | 6 ++++- 10 files changed, 66 insertions(+), 15 deletions(-) create mode 100644 core/src/main/scala/tf/bug/aoc/y2020/Day6.scala diff --git a/core/src/main/scala/tf/bug/aoc/Day.scala b/core/src/main/scala/tf/bug/aoc/Day.scala index 4de0dce..8f1c4d9 100644 --- a/core/src/main/scala/tf/bug/aoc/Day.scala +++ b/core/src/main/scala/tf/bug/aoc/Day.scala @@ -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] +} diff --git a/core/src/main/scala/tf/bug/aoc/Main.scala b/core/src/main/scala/tf/bug/aoc/Main.scala index 79338fa..eb871d1 100644 --- a/core/src/main/scala/tf/bug/aoc/Main.scala +++ b/core/src/main/scala/tf/bug/aoc/Main.scala @@ -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) } + } + +} diff --git a/core/src/main/scala/tf/bug/aoc/Year.scala b/core/src/main/scala/tf/bug/aoc/Year.scala index 8abe910..0831d20 100644 --- a/core/src/main/scala/tf/bug/aoc/Year.scala +++ b/core/src/main/scala/tf/bug/aoc/Year.scala @@ -1,4 +1,5 @@ package tf.bug.aoc -trait Year: +trait Year { def days: Map[Int, Day] +} diff --git a/core/src/main/scala/tf/bug/aoc/y2020/Day1.scala b/core/src/main/scala/tf/bug/aoc/y2020/Day1.scala index f5b2320..dc76d0e 100644 --- a/core/src/main/scala/tf/bug/aoc/y2020/Day1.scala +++ b/core/src/main/scala/tf/bug/aoc/y2020/Day1.scala @@ -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 } + +} diff --git a/core/src/main/scala/tf/bug/aoc/y2020/Day2.scala b/core/src/main/scala/tf/bug/aoc/y2020/Day2.scala index 9e027ac..193186f 100644 --- a/core/src/main/scala/tf/bug/aoc/y2020/Day2.scala +++ b/core/src/main/scala/tf/bug/aoc/y2020/Day2.scala @@ -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) } + +} diff --git a/core/src/main/scala/tf/bug/aoc/y2020/Day3.scala b/core/src/main/scala/tf/bug/aoc/y2020/Day3.scala index 230d17f..91a9ac9 100644 --- a/core/src/main/scala/tf/bug/aoc/y2020/Day3.scala +++ b/core/src/main/scala/tf/bug/aoc/y2020/Day3.scala @@ -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) } + +} diff --git a/core/src/main/scala/tf/bug/aoc/y2020/Day4.scala b/core/src/main/scala/tf/bug/aoc/y2020/Day4.scala index a97f7a9..609e1ae 100644 --- a/core/src/main/scala/tf/bug/aoc/y2020/Day4.scala +++ b/core/src/main/scala/tf/bug/aoc/y2020/Day4.scala @@ -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) } + +} 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 5f67997..613966e 100644 --- a/core/src/main/scala/tf/bug/aoc/y2020/Day5.scala +++ b/core/src/main/scala/tf/bug/aoc/y2020/Day5.scala @@ -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 }) + +} diff --git a/core/src/main/scala/tf/bug/aoc/y2020/Day6.scala b/core/src/main/scala/tf/bug/aoc/y2020/Day6.scala new file mode 100644 index 0000000..8dfc36e --- /dev/null +++ b/core/src/main/scala/tf/bug/aoc/y2020/Day6.scala @@ -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) + } + +} diff --git a/core/src/main/scala/tf/bug/aoc/y2020/y2020.scala b/core/src/main/scala/tf/bug/aoc/y2020/y2020.scala index 322eb3d..3fae2ed 100644 --- a/core/src/main/scala/tf/bug/aoc/y2020/y2020.scala +++ b/core/src/main/scala/tf/bug/aoc/y2020/y2020.scala @@ -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, ) + +}