feat: add day 5

This commit is contained in:
Xavier Morel
2025-05-02 20:49:59 +02:00
committed by installer
parent 568903d4d6
commit 64953fd51a
2 changed files with 76 additions and 0 deletions

View File

@@ -6,6 +6,7 @@ import days._
case 2 => Day2.solve()
case 3 => Day3.solve()
case 4 => Day4.solve()
case 5 => Day5.solve()
case _ => println(s"Day $dayNumber is not yet implemented.")
}
}

View File

@@ -0,0 +1,75 @@
package days
object Day5 extends Day {
val number: Int = 5;
def parseInput(input: String): (Map[Int, List[Int]], List[List[Int]]) = {
val splitted = input.split("\n\n")
// x|y\nx2|y => Map(y -> List(x, x2))
val orderConstraints: Map[Int, List[Int]] = splitted(0).linesIterator
.map(
_.split('|')
.map(_.filter(_ != '|').toInt)
.toList
)
.foldLeft(Map.empty: Map[Int, List[Int]]) {
case (acc, (h :: h2 :: _)) =>
acc.updatedWith(h) {
case Some(existing) => Some(h2 :: existing)
case None => Some(List(h2))
}
case (acc, _) => acc
}
// x,y,z\na,b,c,d => [[x,y,z], [a,b,c,d]]
val batches = splitted(1).linesIterator
.map(_.split(",").map(_.toInt).toList)
.toList
(orderConstraints, batches)
}
def checkBatch(order: Map[Int, List[Int]])(xs: List[Int]): Boolean =
xs.foldLeft(
// Is still OK + List of predecessors
(true, List()): (Boolean, List[Int])
) {
case ((true, prev), x) => {
// Check if predecessors include some page that should actually be after the current
(order(x).forall({ o => !prev.contains(o) }), x :: prev)
}
// If flag is already false, let's keep it that way
case ((false, _), _) => (false, List())
}._1
def fixBatch(order: Map[Int, List[Int]])(xs: List[Int]): List[Int] =
// For each number of the batch
xs
// Get the number of relevant order rules
.map(x => x -> order(x).filter(xs.contains))
// Order by the number of previous pages (incidentally all rules are here)
.sortBy(_._2.length)
// Keep just the page number and voilà
.map(_._1)
def takeMiddleOne(xs: List[Int]): Int =
xs(xs.length / 2)
def part1(input: String) = {
val (order, batches) = parseInput(input)
batches
.filter(checkBatch(order))
.map(takeMiddleOne)
.sum()
.toString
}
def part2(input: String) = {
val (order, batches) = parseInput(input)
batches
.filterNot(checkBatch(order))
.map(fixBatch(order))
.map(takeMiddleOne)
.sum()
.toString
}
}