This commit is contained in:
Aly 2020-12-04 17:26:20 -08:00
parent b9bf5023eb
commit 457f034d73
6 changed files with 60 additions and 12 deletions

View file

@ -5,5 +5,5 @@ import cats.effect._
import fs2._
trait Day:
def part1[F[_]: Sync]: Pipe[F, String, String]
def part2[F[_]: Sync]: Pipe[F, String, String]
def part1[F[_]: Async]: Pipe[F, String, String]
def part2[F[_]: Async]: Pipe[F, String, String]

View file

@ -1,5 +1,6 @@
package tf.bug.aoc
import cats._
import cats.effect._
import cats.effect.std.Console
import cats.syntax.all._
@ -25,8 +26,8 @@ object Main extends IOApp:
.compile.drain
}.as(ExitCode.Success)
def selectYear[F[_]: Sync: Console]: F[Year] =
val ask = Sync[F].delay(print("Select 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)
year.flatMap {
@ -34,8 +35,8 @@ object Main extends IOApp:
case None => selectYear[F]
}
def selectDay[F[_]: Sync: Console](year: Year): F[Day] =
val ask = Sync[F].delay(print("Select 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)
day.flatMap {
@ -43,8 +44,8 @@ object Main extends IOApp:
case None => selectDay[F](year)
}
def selectPart[F[_]: Sync: Console](day: Day): F[Pipe[F, String, String]] =
val ask = Sync[F].delay(print("Select part: "))
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)
part.flatMap {

View file

@ -10,10 +10,10 @@ import tf.bug.aoc.Day
object Day1 extends Day:
override def part1[F[_]: Sync]: Pipe[F, String, String] =
override def part1[F[_]: Async]: Pipe[F, String, String] =
parts[F](2)
override def part2[F[_]: Sync]: Pipe[F, String, String] =
override def part2[F[_]: Async]: Pipe[F, String, String] =
parts[F](3)
def parts[F[_]: Sync](nums: Int): Pipe[F, String, String] =

View file

@ -23,13 +23,13 @@ object Day2 extends Day:
Entry(policy, password)
}
override def part1[F[_]: Sync]: Pipe[F, String, String] =
override def part1[F[_]: Async]: Pipe[F, String, String] =
parts[F] { ent =>
val charCount = ent.password.count(_ == ent.policy.letter)
ent.policy.min <= charCount && charCount <= ent.policy.max
}
override def part2[F[_]: Sync]: Pipe[F, String, String] =
override def part2[F[_]: Async]: Pipe[F, String, String] =
parts[F] { ent =>
val a = ent.policy.min <= ent.password.length && ent.password.charAt(ent.policy.min - 1) == ent.policy.letter
val b = ent.policy.max <= ent.password.length && ent.password.charAt(ent.policy.max - 1) == ent.policy.letter

View file

@ -0,0 +1,46 @@
package tf.bug.aoc.y2020
import cats.effect._
import cats.syntax.all._
import fs2._
import tf.bug.aoc.Day
object Day3 extends Day:
case class Path(x: Int, treeCount: Long)
override def part1[F[_]: Async]: Pipe[F, String, String] =
_.through(checkSlope[F](3, 1)).map(_.show)
override def part2[F[_]: Async]: Pipe[F, String, String] =
(lines: Stream[F, String]) => {
val pipes: Vector[Pipe[F, String, Long]] = Vector(
checkSlope[F](1, 1),
checkSlope[F](3, 1),
checkSlope[F](5, 1),
checkSlope[F](7, 1),
checkSlope[F](1, 2),
)
val broadcast: Stream[F, String] => Stream[F, Stream[F, String]] = concurrent.Broadcast[F, String](pipes.size)
val channels: Stream[F, Stream[F, String]] = lines.through(broadcast).take(pipes.size)
val results: Stream[F, Long] = channels.zipWithIndex.map {
case (channel, ind) =>
val pipe = pipes(ind.toInt)
channel.through(pipe)
}.parJoin(pipes.size)
results.fold(1L)(_ * _).map(_.show)
}
def checkSlope[F[_]](right: Int, down: Int): Pipe[F, String, Long] =
(lines: Stream[F, String]) => {
lines.chunkN(down, true).fold(Path(0, 0L)) {
case (Path(x, numTrees), group) =>
group.head match {
case Some(line) =>
val isTree = line.charAt(x % line.length) == '#'
Path(x + right, if(isTree) numTrees + 1L else numTrees)
case None =>
Path(x, numTrees)
}
}.map(_.treeCount)
}

View file

@ -6,4 +6,5 @@ object y2020 extends Year:
override def days: Map[Int, Day] = Map(
1 -> Day1,
2 -> Day2,
3 -> Day3,
)