Skip to content

Commit

Permalink
Solve 2023 day 19 part 2
Browse files Browse the repository at this point in the history
  • Loading branch information
sim642 committed Dec 19, 2023
1 parent 818c61b commit dbe9454
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 1 deletion.
69 changes: 68 additions & 1 deletion src/main/scala/eu/sim642/adventofcode2023/Day19.scala
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package eu.sim642.adventofcode2023

import eu.sim642.adventofcodelib.box.Box4
import eu.sim642.adventofcodelib.pos.Pos4

import scala.annotation.tailrec


Expand All @@ -11,6 +14,8 @@ object Day19 {
def totalRating: Int = ratings.values.sum
}

type PartBox = Box4

enum Comparison {
case Lt
case Gt
Expand All @@ -31,6 +36,33 @@ object Day19 {
case _ => None
}
}

// TODO: simplify
private val (trueBox, falseBox): (PartBox, PartBox) = (category, comparison) match {
case ('x', Comparison.Lt) =>
(Box4(Pos4(1, 1, 1, 1), Pos4(rating - 1, 4000, 4000, 4000)), Box4(Pos4(rating, 1, 1, 1), Pos4(4000, 4000, 4000, 4000)))
case ('m', Comparison.Lt) =>
(Box4(Pos4(1, 1, 1, 1), Pos4(4000, rating - 1, 4000, 4000)), Box4(Pos4(1, rating, 1, 1), Pos4(4000, 4000, 4000, 4000)))
case ('a', Comparison.Lt) =>
(Box4(Pos4(1, 1, 1, 1), Pos4(4000, 4000, rating - 1, 4000)), Box4(Pos4(1, 1, rating, 1), Pos4(4000, 4000, 4000, 4000)))
case ('s', Comparison.Lt) =>
(Box4(Pos4(1, 1, 1, 1), Pos4(4000, 4000, 4000, rating - 1)), Box4(Pos4(1, 1, 1, rating), Pos4(4000, 4000, 4000, 4000)))
case ('x', Comparison.Gt) =>
(Box4(Pos4(rating + 1, 1, 1, 1), Pos4(4000, 4000, 4000, 4000)), Box4(Pos4(1, 1, 1, 1), Pos4(rating, 4000, 4000, 4000)))
case ('m', Comparison.Gt) =>
(Box4(Pos4(1, rating + 1, 1, 1), Pos4(4000, 4000, 4000, 4000)), Box4(Pos4(1, 1, 1, 1), Pos4(4000, rating, 4000, 4000)))
case ('a', Comparison.Gt) =>
(Box4(Pos4(1, 1, rating + 1, 1), Pos4(4000, 4000, 4000, 4000)), Box4(Pos4(1, 1, 1, 1), Pos4(4000, 4000, rating, 4000)))
case ('s', Comparison.Gt) =>
(Box4(Pos4(1, 1, 1, rating + 1), Pos4(4000, 4000, 4000, 4000)), Box4(Pos4(1, 1, 1, 1), Pos4(4000, 4000, 4000, rating)))
case (_, _) => ???
}

def apply(partBox: PartBox): Map[PartBox, Option[Verdict]] = {
val trueMap = (partBox intersect trueBox).map(_ -> Option.apply(verdict)).toMap
val falseMap = (partBox intersect falseBox).map(_ -> Option.empty[Verdict]).toMap
trueMap ++ falseMap
}
}

case class Workflow(rules: List[Rule], fallback: Verdict) {
Expand All @@ -39,13 +71,28 @@ object Day19 {
@tailrec
def helper(rules: List[Rule]): Verdict = rules match {
case Nil => fallback
case rule :: newRules => rule(part) match
case rule :: newRules => rule(part) match {
case Some(verdict) => verdict
case None => helper(newRules)
}
}

helper(rules)
}

def apply(partBox: PartBox): Map[PartBox, Verdict] = {

def helper(rules: List[Rule], partBox: PartBox): Map[PartBox, Verdict] = rules match {
case Nil => Map(partBox -> fallback)
case rule :: newRules =>
rule(partBox).flatMap({
case (partBox, Some(verdict)) => Map(partBox -> verdict)
case (partBox, None) => helper(newRules, partBox)
})
}

helper(rules, partBox)
}
}

case class Input(workflows: Map[String, Workflow], parts: Seq[Part]) {
Expand All @@ -60,11 +107,30 @@ object Day19 {

helper("in")
}

def apply(partBox: PartBox): Set[PartBox] = {

def helper(workflow: String, partBox: PartBox): Set[PartBox] = {
val verdicts = workflows(workflow)(partBox)
verdicts.flatMap({
case (partBox, Verdict.Accept) => Set(partBox)
case (_, Verdict.Reject) => Set.empty
case (partBox, Verdict.Continue(workflow)) => helper(workflow, partBox)
}).toSet
}

helper("in", partBox)
}
}

def totalAcceptedRating(input: Input): Int =
input.parts.filter(input(_)).map(_.totalRating).sum

def countAllAccepted(input: Input): Long = {
val partBox = Box4(Pos4(1, 1, 1, 1), Pos4(4000, 4000, 4000, 4000))
input(partBox).map(_.size[Long]).sum
}


def parsePart(s: String): Part = s match {
case s"{$ratings}" =>
Expand Down Expand Up @@ -107,5 +173,6 @@ object Day19 {

def main(args: Array[String]): Unit = {
println(totalAcceptedRating(parseInput(input)))
println(countAllAccepted(parseInput(input)))
}
}
8 changes: 8 additions & 0 deletions src/test/scala/eu/sim642/adventofcode2023/Day19Test.scala
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,12 @@ class Day19Test extends AnyFunSuite {
test("Part 1 input answer") {
assert(totalAcceptedRating(parseInput(input)) == 418498)
}

test("Part 2 examples") {
assert(countAllAccepted(parseInput(exampleInput)) == 167409079868000L)
}

test("Part 2 input answer") {
assert(countAllAccepted(parseInput(input)) == 123331556462603L)
}
}

0 comments on commit dbe9454

Please sign in to comment.