Skip to content

Commit 9218e5d

Browse files
committed
Day 5: part 2
1 parent a80614c commit 9218e5d

File tree

2 files changed

+40
-1
lines changed

2 files changed

+40
-1
lines changed

src/main/scala/Day05.scala

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import cats.Eq
2-
import cats.data.NonEmptyList
2+
import cats.data.{NonEmptyList, NonEmptyVector}
33
import cats.derived.*
44
import cats.syntax.all.*
5+
import scala.annotation.tailrec
56

67
object Day05:
78

@@ -21,6 +22,10 @@ object Day05:
2122

2223
case class Update(pages: NonEmptyList[Page]):
2324

25+
val toNev: NonEmptyVector[Page] = pages.toNev
26+
27+
val toNevWithIndex: NonEmptyVector[(Page, Int)] = toNev.zipWithIndex
28+
2429
def allOrderRules: List[OrderRule] = pages.toList.zip(pages.tail).map(OrderRule.apply)
2530

2631
def middlePage: Page =
@@ -30,6 +35,18 @@ object Day05:
3035
def firstViolatedOrderRules(rules: NonEmptyList[OrderRule]): Option[OrderRule] =
3136
allOrderRules.map(_.reverse).find(rules.contains_)
3237

38+
def swap(p1: Page, p2: Page): Update =
39+
(toNevWithIndex.find(_._1 == p1), toNevWithIndex.find(_._1 == p2)).tupled.fold(ifEmpty = this) {
40+
case ((_, i1), (_, i2)) => Update(pages = toNev.updatedUnsafe(i1, p2).updatedUnsafe(i2, p1).toNonEmptyList)
41+
}
42+
43+
@tailrec
44+
final def fixed(rules: NonEmptyList[OrderRule]): Update =
45+
firstViolatedOrderRules(rules) match {
46+
case Some(r) => swap(r.before, r.after).fixed(rules)
47+
case None => this
48+
}
49+
3350
object Update:
3451
def parse(s: String): Option[Update] = s.split(',').toList.toNel.flatMap(_.traverse(Page.parse).map(Update.apply))
3552

@@ -47,6 +64,14 @@ object Day05:
4764
.collect(u => filteredRules(u).toNel.flatMap(u.firstViolatedOrderRules) match { case None => u })
4865
.foldMap(_.middlePage.n)
4966

67+
def fixedIncorrectlyOrderedUpdatesMiddlePageSum: Int =
68+
updates.collect { u =>
69+
filteredRules(u).toNel.flatMap(rs => u.firstViolatedOrderRules(rs).map((rs, _))) match {
70+
case Some((rulesForUpdate, _)) => (u, rulesForUpdate)
71+
}
72+
}.map((u, rulesForUpdate) => u.fixed(rulesForUpdate))
73+
.foldMap(_.middlePage.n)
74+
5075
object Input:
5176
def parse(rows: List[String]): Option[Input] =
5277
rows.splitBySeparator("") match {

src/test/scala/Day05Suite.scala

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,20 @@ class Day05Suite extends ScalaCheckSuite:
118118
5_064.some
119119
)
120120

121+
// part 2
122+
123+
test("small input incorrectly ordered updates middle page sum is 123"):
124+
assertEquals(
125+
Input.parse(smallInput).map(_.fixedIncorrectlyOrderedUpdatesMiddlePageSum),
126+
123.some
127+
)
128+
129+
test("big input incorrectly ordered updates middle page sum is 5_152"):
130+
assertEquals(
131+
Input.parse(bigInput).map(_.fixedIncorrectlyOrderedUpdatesMiddlePageSum),
132+
5_152.some
133+
)
134+
121135
object Day05Suite:
122136

123137
val bigInput: List[String] = getLinesFromFile("src/test/scala/day05_input.txt")

0 commit comments

Comments
 (0)