-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
8135118
commit 998d5e0
Showing
3 changed files
with
1,081 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
import Day02.Safety.* | ||
import cats.data.NonEmptyList | ||
import cats.syntax.all.* | ||
|
||
object Day02: | ||
|
||
case class Level(value: Int): | ||
def differsFrom(min: Int, max: Int)(that: Level): Boolean = | ||
Math.abs(value - that.value) >= min && Math.abs(value - that.value) <= max | ||
|
||
object Level: | ||
|
||
given Ordering[Level] = Ordering.by(_.value) | ||
|
||
def parse(s: String): Option[Level] = s.toIntOption.map(Level.apply) | ||
|
||
enum Safety: | ||
case Safe, Unsafe | ||
|
||
case class Report(levels: NonEmptyList[Level]): | ||
|
||
def isAllIncreasing: Boolean = levels.toList == levels.toList.sorted | ||
def isAllDecreasing: Boolean = levels.toList == levels.toList.sorted.reverse | ||
def areAllDeltasBetween1And3: Boolean = | ||
levels.toList.zip(levels.tail).forall((l, r) => l.differsFrom(min = 1, max = 3)(r)) | ||
|
||
def safety: Safety = if ((isAllIncreasing || isAllDecreasing) && areAllDeltasBetween1And3) Safe else Unsafe | ||
|
||
object Report: | ||
def parse(s: String): Option[Report] = s.split(' ').toList.traverse(Level.parse).flatMap(_.toNel.map(Report.apply)) | ||
|
||
def parse(input: List[String]): Option[List[Report]] = input.traverse(Report.parse) | ||
|
||
def safetyCount(input: List[String]): Option[Int] = | ||
parse(input).map(_.foldMap(_.safety match | ||
case Safe => 1 | ||
case Unsafe => 0 | ||
)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
import Day02.* | ||
import Day02Suite.* | ||
import cats.data.NonEmptyList | ||
import munit.ScalaCheckSuite | ||
|
||
class Day02Suite extends ScalaCheckSuite: | ||
|
||
test("parsing small input"): | ||
assertEquals( | ||
parse(smallInput), | ||
Some( | ||
List( | ||
NonEmptyList.of(7, 6, 4, 2, 1).map(Level.apply), | ||
NonEmptyList.of(1, 2, 7, 8, 9).map(Level.apply), | ||
NonEmptyList.of(9, 7, 6, 2, 1).map(Level.apply), | ||
NonEmptyList.of(1, 3, 2, 4, 5).map(Level.apply), | ||
NonEmptyList.of(8, 6, 4, 4, 1).map(Level.apply), | ||
NonEmptyList.of(1, 3, 6, 7, 9).map(Level.apply) | ||
).map(Report.apply) | ||
) | ||
) | ||
|
||
test("parsing big input returns a proper reports list"): | ||
assert(parse(bigInput).isDefined) | ||
|
||
test("safety count for small input is 2"): | ||
assertEquals(safetyCount(smallInput), Some(2)) | ||
|
||
test("safety count for big input is 490"): | ||
assertEquals(safetyCount(bigInput), Some(490)) | ||
|
||
object Day02Suite: | ||
|
||
val bigInput: List[String] = getLinesFromFile("src/test/scala/day02_input.txt") | ||
|
||
val smallInput: List[String] = List( | ||
"7 6 4 2 1", | ||
"1 2 7 8 9", | ||
"9 7 6 2 1", | ||
"1 3 2 4 5", | ||
"8 6 4 4 1", | ||
"1 3 6 7 9" | ||
) |
Oops, something went wrong.