From f1f52f37455e27ceee18c9d04d4c14b423e676ad Mon Sep 17 00:00:00 2001 From: Simmo Saan Date: Sun, 25 Dec 2022 20:15:18 +0200 Subject: [PATCH] Add derivative solution to 2022 day 21 part 2 --- .../eu/sim642/adventofcode2022/Day21.scala | 38 +++++++++++++++++++ .../sim642/adventofcode2022/Day21Test.scala | 3 ++ 2 files changed, 41 insertions(+) diff --git a/src/main/scala/eu/sim642/adventofcode2022/Day21.scala b/src/main/scala/eu/sim642/adventofcode2022/Day21.scala index 2d07150b..6ed1a256 100644 --- a/src/main/scala/eu/sim642/adventofcode2022/Day21.scala +++ b/src/main/scala/eu/sim642/adventofcode2022/Day21.scala @@ -170,6 +170,44 @@ object Day21 { } } + /** + * Solution, which finds the derivative w.r.t. humn to get the slope + * and then solves linear equation to find humn. + * Assumes expression is linear w.r.t. humn. + */ + object DerivativePart2Solution extends Part2Solution { + + override def findHumn(monkeys: Monkeys): Long = { + val humnMonkeys = makeHumnMonkeys(monkeys) + (humn -> Job.Number(0)) // evaluate at 0 + val evalName = makeEvalName[BigDecimal](humnMonkeys).andThen(_.get) // always get, because all variables set + + def deriveName(name: String): BigDecimal = { + if (name == humn) + 1 + else + deriveJob(humnMonkeys(name)) + } + + def deriveJob(job: Job): BigDecimal = job match { + case Job.Number(_) => 0 + case Job.Operation(lhs, op, rhs) => + op match { + case Op.Add => deriveName(lhs) + deriveName(rhs) + case Op.Sub => deriveName(lhs) - deriveName(rhs) + case Op.Mul => + deriveName(lhs) * evalName(rhs) + evalName(lhs) * deriveName(rhs) + case Op.Div => + (deriveName(lhs) * evalName(rhs) - evalName(lhs) * deriveName(rhs)) / (evalName(rhs) * evalName(rhs)) + } + } + + val y0 = evalName(root) + val dy0 = deriveName(root) // derivative at 0 + val x0 = y0 / -dy0 + x0.setScale(0, BigDecimal.RoundingMode.HALF_UP).longValue + } + } + def parseMonkey(s: String): (String, Job) = s match { case s"$name: $lhs $opStr $rhs" => diff --git a/src/test/scala/eu/sim642/adventofcode2022/Day21Test.scala b/src/test/scala/eu/sim642/adventofcode2022/Day21Test.scala index 90f7e389..3f11522a 100644 --- a/src/test/scala/eu/sim642/adventofcode2022/Day21Test.scala +++ b/src/test/scala/eu/sim642/adventofcode2022/Day21Test.scala @@ -10,6 +10,7 @@ class Day21Test extends Suites( new InvertPart2SolutionTest, new BinarySearchPart2SolutionTest, new LinearPart2SolutionTest, + new DerivativePart2SolutionTest, ) object Day21Test { @@ -58,4 +59,6 @@ object Day21Test { class BinarySearchPart2SolutionTest extends Part2SolutionTest(BinarySearchPart2Solution) class LinearPart2SolutionTest extends Part2SolutionTest(LinearPart2Solution) + + class DerivativePart2SolutionTest extends Part2SolutionTest(DerivativePart2Solution) }