mirror of
https://github.com/mx42/aoc2024.scala.git
synced 2026-01-13 21:39:52 +01:00
feat: add day 5
This commit is contained in:
@@ -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.")
|
||||
}
|
||||
}
|
||||
|
||||
75
src/main/scala/days/Day5.scala
Normal file
75
src/main/scala/days/Day5.scala
Normal 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
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user