59 lines
1.7 KiB
TypeScript
59 lines
1.7 KiB
TypeScript
import { parseInput, Workflow } from "./parser.ts";
|
|
import { partition, MaterialRange } from "./range.ts";
|
|
|
|
const input = await Deno.readTextFile("input.txt");
|
|
const parsed = parseInput(input);
|
|
|
|
|
|
class Executor {
|
|
workflowTable: Map<string, Workflow>
|
|
constructor(rules: Workflow[]) {
|
|
this.workflowTable = new Map();
|
|
for (const rule of rules) {
|
|
this.workflowTable.set(rule.name, rule);
|
|
}
|
|
}
|
|
|
|
caculRange(start: string, material: MaterialRange) {
|
|
if (start === "A") {
|
|
return [material];
|
|
}
|
|
if (start === "R") {
|
|
return [];
|
|
}
|
|
const gotoRules = this.workflowTable.get(start)!;
|
|
|
|
const ret = [] as MaterialRange[];
|
|
let dest = gotoRules.always;
|
|
for (const rule of gotoRules.rules) {
|
|
const cond = partition(rule.condition, material)
|
|
if (cond === null) {
|
|
// skip
|
|
continue;
|
|
}
|
|
else if (cond instanceof Array) {
|
|
const [falseRange, trueRange] = cond;
|
|
ret.push(...this.caculRange(rule.dest, trueRange));
|
|
material = falseRange;
|
|
}
|
|
else {
|
|
dest = rule.dest;
|
|
break;
|
|
}
|
|
}
|
|
ret.push(...this.caculRange(dest, material));
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
const executor = new Executor(parsed.rules);
|
|
const ranges = executor.caculRange("in", {
|
|
x: [1, 4000],
|
|
m: [1, 4000],
|
|
a: [1, 4000],
|
|
s: [1, 4000]
|
|
});
|
|
const countRange = (x: [number, number])=> x[1] - x[0] + 1;
|
|
console.log(ranges.map(r=> {
|
|
return countRange(r.x) * countRange(r.m) * countRange(r.a) * countRange(r.s);
|
|
}).reduce((a, b) => a + b, 0)) |