-
Notifications
You must be signed in to change notification settings - Fork 5
/
p21.noul
39 lines (35 loc) · 1016 Bytes
/
p21.noul
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
day := 21;
import "advent-prelude.noul";
puzzle_input := advent_input();
solve := \h -> (
known := {};
if (h != null) known["humn"] = h;
while (1) for (line <- puzzle_input.lines) (
lhs, rhs := line split ": ";
if (lhs in known) continue;
switch (rhs.words)
case d, -> (known[lhs] = int(d))
case a, op, b -> (
switch ([known !? a, known !? b])
case av != null, bv != null -> (
known[lhs] = eval(op)(av, bv);
if (lhs == "root") return [known[lhs], av, bv];
)
case _ -> null
)
)
);
submit! 1, solve(null)[0];
# binary search from bounds found manually; i'm too lazy to work out a
# reasonably general way to juggle the sign possibilities (and this strategy
# obviously doesn't work for general inputs anyway since rational polynomials
# aren't monotonic)
lo := 1000000000000; # lhs > rhs
hi := 10000000000000; # lhs < rhs
while (1) (
mid := (lo + hi) // 2;
switch (solve(mid)[1:] apply <=>)
case 0 -> (submit(2, mid); break)
case 1 -> (lo = mid)
case -1 -> (hi = mid)
)