Skip to content

Commit 27c7703

Browse files
committed
Inverse method
1 parent cb5b674 commit 27c7703

File tree

2 files changed

+50
-27
lines changed

2 files changed

+50
-27
lines changed

src/main/scala/AdventOfCode2022/Day21.scala

Lines changed: 49 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,61 @@
11
package AdventOfCode2022
22

33
object Day21:
4-
def parse(input: Seq[String], part2: Boolean): collection.mutable.Map[String, () => Long] =
5-
val monkeys = collection.mutable.Map[String, () => Long]()
6-
input.foreach { line =>
7-
val Array(name, rest: _*) = line.split("[: ]+"): @unchecked
8-
monkeys(name) = rest match
9-
case Seq(number) => () => number.toLong
10-
case Seq(left, operation, right) => operation match
11-
case _ if name == "root" && part2 => () => (monkeys(left)() - monkeys(right)()).abs
12-
case "+" => () => monkeys(left)() + monkeys(right)()
13-
case "-" => () => monkeys(left)() - monkeys(right)()
14-
case "*" => () => monkeys(left)() * monkeys(right)()
15-
case "/" => () => monkeys(left)() / monkeys(right)()
4+
sealed trait Monkey
5+
case class Number(value: Long) extends Monkey
6+
case class Operation(left: String, operation: String, right: String) extends Monkey
7+
8+
def parse(input: Seq[String]): Map[String, Monkey] =
9+
input.map {
10+
case s"$name: $left $operation $right" => name -> Operation(left, operation, right)
11+
case s"$name: $value" => name -> Number(value.toLong)
1612
}
17-
monkeys
13+
.toMap
1814

19-
def part1(input: Seq[String]): Long = parse(input, false)("root")()
15+
def calculate(monkeys: Map[String, Monkey]): Map[String, Long] =
16+
val result = collection.mutable.Map[String, Long]()
17+
def compute(name: String) = result.getOrElseUpdate(name, helper(name))
18+
def helper(name: String): Long = monkeys(name) match
19+
case Number(value) => value
20+
case Operation(left, operation, right) => operation match
21+
case "+" => compute(left) + compute(right)
22+
case "-" => compute(left) - compute(right)
23+
case "*" => compute(left) * compute(right)
24+
case "/" => compute(left) / compute(right)
2025

21-
def part2(input: Seq[String]): Long =
22-
val monkeys = parse(input, true)
26+
compute("root")
27+
result.toMap
28+
end calculate
2329

24-
def check(n: Long): Long =
25-
monkeys("humn") = () => n
26-
monkeys("root")()
30+
def part1(input: Seq[String]): Long =
31+
val monkeys = parse(input)
32+
val results = calculate(monkeys)
33+
results("root")
34+
35+
def part2(input: Seq[String]): Long =
36+
val monkeys = parse(input)
37+
val results = calculate(monkeys)
2738

28-
def helper(prev: Long, n: Long, step: Long): Long =
29-
val next = n + step
30-
val result = check(next)
31-
if result == 0 then next
32-
else if result < prev then helper(result, next, step)
33-
else helper(result, next, step / -2)
39+
def helper(name: String, value: Long): Option[Long] = monkeys(name) match
40+
case Number(_) => Option.when(name == "humn")(value)
41+
case Operation(left, _, right) if name == "root" =>
42+
val first = helper(right, results(left))
43+
val second = helper(left, results(right))
44+
first.orElse(second)
45+
case Operation(left, operation, right) =>
46+
val first = operation match
47+
case "+" => helper(right, value - results(left))
48+
case "-" => helper(right, results(left) - value)
49+
case "*" => if results(left) != 0 then helper(right, value / results(left)) else None
50+
case "/" => if value != 0 then helper(right, results(left) / value) else None
51+
val second = operation match
52+
case "+" => helper(left, value - results(right))
53+
case "-" => helper(left, value + results(right))
54+
case "*" => if results(right) != 0 then helper(left, value / results(right)) else None
55+
case "/" => helper(left, value * results(right))
56+
first.orElse(second)
3457

35-
helper(check(0), 0, 1 << 60)
58+
helper("root", -1).get
3659
end part2
3760

3861
def main(args: Array[String]): Unit =

src/test/scala/AdventOfCode2022/Day21Suite.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,5 +25,5 @@ class Day21Suite extends AnyFunSuite:
2525
}
2626

2727
test("Part 2 should handle sample input correctly") {
28-
assert(Day21.part2(sample) == 302)
28+
assert(Day21.part2(sample) == 301)
2929
}

0 commit comments

Comments
 (0)