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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
|
import * as fs from "fs";
const simple = /(\w+): (\d+)/;
const operation = /(\w+): (\w+) ([+\-*/]) (\w+)/;
class Monkey {
constructor(line) {
// left and right are temporarily strings
this.left = null;
this.right = null;
this.up = null;
const s = line.match(simple);
if (s) {
this.name = s[1];
this.value = BigInt(s[2]);
} else {
const o = line.match(operation);
if (!o) throw "wtf";
this.name = o[1];
this.left = o[2];
this.operation = o[3];
this.right = o[4];
this.value = undefined;
}
}
solve(m, input) {
if (this.name === "humn") {
throw "unreachable humn";
}
if (this.value !== undefined) {
console.log (this.name, " = ", this.value);
return this.value;
}
switch(m) {
case this.up: return this.solveUp(input);
case this.left: return this.solveLeft(input);
case this.right: return this.solveRight(input);
default: throw "unreachable";
}
}
solveUp(input) {
if (this.name === "root") {
throw "unreachable";
}
const left = input[this.left].solve(this.name, input);
const right = input[this.right].solve(this.name, input);
console.log("UP\t", this.name, " = ", this.left, "(", left, ") ", this.operation, " ", this.right, " (", right, ")");
switch(this.operation) { // up = left op right
case "+": return left + right;
case "-": return left - right;
case "*": return left * right;
case "/": return left / right;
default: throw "unreachable";
}
}
solveLeft(input) {
if (this.name === "root") {
const root = input[this.right].solve(this.name, input);
console.log("root = ", root);
return root;
}
const up = input[this.up].solve(this.name, input);
const right = input[this.right].solve(this.name, input);
console.log("LEFT\t", this.name, "(", up, ") = ", this.left, this.operation, " ", this.right, " (", right, ")");
switch(this.operation) { // left = up invop right
case "+": return up - right;
case "-": return up + right;
case "*": return up / right;
case "/": return up * right;
default: throw "unreachable";
}
}
solveRight(input) {
if (this.name === "root") {
const root = input[this.left].solve(this.name, input);
console.log("root = ", root);
return root;
}
const up = input[this.up].solve(this.name, input);
const left = input[this.left].solve(this.name, input);
console.log("RIGHT\t", this.name, "(", up, ") = ", this.left, "(", left, ") ", this.operation, " ", this.right);
switch(this.operation) { // right = up invop right
case "+": return up - left;
case "-": return left - up;
case "*": return up / left;
case "/": return left / up;
default: throw "unreachable";
}
}
print() {
console.log(this.name, this.value);
}
}
function load(filename) {
let res = {};
fs.readFileSync(filename, "utf8")
.trim()
.split("\n")
.forEach(line => {
let m = new Monkey(line);
res[m.name] = m;
});
Object.values(res).forEach(m => {
if (m.value === undefined) {
res[m.right].up = m.name;
res[m.left].up = m.name;
}
});
return res;
}
let example = load("example");
let input = load("input");
function solve(input) {
let h = input["humn"];
return input[h.up].solve(h.name, input);
}
const exampleOutput = solve(example);
if (exampleOutput !== 301n) {
console.log("Example failed with " + exampleOutput);
process.exit(1); // eslint-disable-line
}
console.log(solve(input));
|