aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--2022/21-Monkey-Math/second.js127
1 files changed, 127 insertions, 0 deletions
diff --git a/2022/21-Monkey-Math/second.js b/2022/21-Monkey-Math/second.js
new file mode 100644
index 0000000..6932e13
--- /dev/null
+++ b/2022/21-Monkey-Math/second.js
@@ -0,0 +1,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));