@@ -170,6 +170,44 @@ object Day21 {
170
170
}
171
171
}
172
172
173
+ /**
174
+ * Solution, which finds the derivative w.r.t. humn to get the slope
175
+ * and then solves linear equation to find humn.
176
+ * Assumes expression is linear w.r.t. humn.
177
+ */
178
+ object DerivativePart2Solution extends Part2Solution {
179
+
180
+ override def findHumn (monkeys : Monkeys ): Long = {
181
+ val humnMonkeys = makeHumnMonkeys(monkeys) + (humn -> Job .Number (0 )) // evaluate at 0
182
+ val evalName = makeEvalName[BigDecimal ](humnMonkeys).andThen(_.get) // always get, because all variables set
183
+
184
+ def deriveName (name : String ): BigDecimal = {
185
+ if (name == humn)
186
+ 1
187
+ else
188
+ deriveJob(humnMonkeys(name))
189
+ }
190
+
191
+ def deriveJob (job : Job ): BigDecimal = job match {
192
+ case Job .Number (_) => 0
193
+ case Job .Operation (lhs, op, rhs) =>
194
+ op match {
195
+ case Op .Add => deriveName(lhs) + deriveName(rhs)
196
+ case Op .Sub => deriveName(lhs) - deriveName(rhs)
197
+ case Op .Mul =>
198
+ deriveName(lhs) * evalName(rhs) + evalName(lhs) * deriveName(rhs)
199
+ case Op .Div =>
200
+ (deriveName(lhs) * evalName(rhs) - evalName(lhs) * deriveName(rhs)) / (evalName(rhs) * evalName(rhs))
201
+ }
202
+ }
203
+
204
+ val y0 = evalName(root)
205
+ val dy0 = deriveName(root) // derivative at 0
206
+ val x0 = y0 / - dy0
207
+ x0.setScale(0 , BigDecimal .RoundingMode .HALF_UP ).longValue
208
+ }
209
+ }
210
+
173
211
174
212
def parseMonkey (s : String ): (String , Job ) = s match {
175
213
case s " $name: $lhs $opStr $rhs" =>
0 commit comments