https://github.com/lsug/advent-of-code-typelevel
git checkout day-1-step-0
sbt compile test
# go to advent/solutions/Day1.scala and fix the tests
Code a functional solution to Part 1
git diff day-1-step-0 day-1-step-1
def fuel(mass: Int): Int =
(mass / 3) - 2
def calculateFuels(masses: List[Int]): List[Int] =
masses.map(fuel)
def sumFuels(fuels: List[Boolean]): Int =
fuels.sum
def sumOfFuel(masses: List[Boolean]): Int =
sumFuels(calculateFuels(masses))
def weLikeCats: Boolean = ???
def weLikeCats(b: Boolean): Boolean = ???
def weLikeCats[A](a: A): A = ???
def weLikeCats(b: Boolean): Boolean = ???
git checkout day-1-step-1-abstraction
sbt compile test
# go to advent/solutions/Abstraction.scala and fix the tests
Complete the Abstraction exercises
def fold[A, B](o: Option[A], f: A => B, b: B): B = {
o match {
case None => b
case Some(v) => f(v)
}
}
def list[A]: List[A] = Nil
def fuel[A](mass: A): A = {
(mass / 3) - 2
}
def fuel[A](mass: A)
(quotient: (A, A) => A,
minus: (A, A) => A,
two: A,
three: A): A = {
minus(quotient(mass, three), two)
}
fuel(12)(_ / _, _ - _, 2, 3)
trait Mass[A] {
def quotient(a: A, b: A): A
def minus(a: A, b: A): A
def two: A
def three: A
}
def fuel[A](mass: A)(M: Mass[A]): A =
M.minus(M.quotient(mass, M.three), M.two)
val intHasMass: Mass[Int] = new Mass[Int] {
def quotient(a: Int, b: Int): Int = a / b
def minus(a: Int, b: Int): Int = a - b
def two: Int = 2
def three: Int = 3
}
fuel[Int](12)(intHasMass)
def fuel[A](mass: A)(implicit M: Mass[A]): A
implicit val intHasMass: Mass[Int] =
new Mass[Int] {
// code
}
fuel(12)
# peek at the solution if you need to
git diff day-1-step-1 day-1-step-2
Create a Mass typeclass and use it in the fuel function
((a combine b) combine c) should be (a combine (b combine c))
trait Semigroup[A] {
def combine(a: A, b: A): A
}
(a combine empty) should be(empty combine a)
(a combine empty) should be(a)
trait Monoid[A] extends Semigroup[A] {
def empty: A
}
import cats._
import cats.implicits._
def sumFuels[A](fuels: List[A])
(implicit M: Monoid[A]): A = ???
git checkout day-1-step-2
Use a monoid for sumFuels and sumOfFuel
git diff day-1-step-2 day-1-step-3
git checkout day-1-step-3
sbt compile test
# go to advent/solutions/Day1.scala and fix the tests
Code a functional solution to Part 2
git diff day-1-step-3 day-1-step-4
trait Order[A] {
def eqv(a: A, b: A): Boolean
def compare(a: A, b: A): Int
}
a < b
git checkout day-1-step-4
Use Monoid and Order in Part 2
git diff day-1-step-4 day-1-step-5
fa.map(f).map(g) should be fa.map(f.andThen(g))
trait Functor[F[_]] {
def map[A, B](fa: F[A])(f: A => B): F[B]
}
fa.map(x => x) = fa
trait Foldable[F[_]] {
def foldLeft[A, B](fa: F[A], b: B)(f: (B, A) => B): B
}
git checkout day-1-step-5
Use Functor and Foldable in Part 1
git diff day-1-step-5 day-1-step-6