jsadvent/solutions/2015/7.js
2020-12-12 00:59:44 -06:00

84 lines
2 KiB
JavaScript

const { Glib, fn } = require('../../lib');
const COMMANDS = {
AND: Symbol('AND'),
OR: Symbol('OR'),
LSHIFT: Symbol('LSHIFT'),
RSHIFT: Symbol('RSHIFT'),
NOT: Symbol('NOT'),
_NO_OP: Symbol('_NO_OP'),
};
const NO_OP = /^(\w+|\d+) -> (\w+)/;
const UNARY_OP = /^(\w+) (\w+) -> (\w+)/;
const BINARY_OP = /^(\w+) (\w+) (\w+|\d+) -> (\w+)$/;
const parse = (input) =>
Glib.fromLines(input)
.map((l) => {
if (l.match(NO_OP)) {
const [str, value, target] = NO_OP.exec(l);
return [target, { command: COMMANDS._NO_OP, args: [value] }];
}
if (l.match(UNARY_OP)) {
const [str, cmd, input, target] = UNARY_OP.exec(l);
return [target, { command: COMMANDS[cmd], args: [input] }];
}
if (l.match(BINARY_OP)) {
const [str, left, cmd, right, target] = BINARY_OP.exec(l);
return [target, { command: COMMANDS[cmd], args: [left, right] }];
}
throw new Error('unable to parse');
})
.toMap();
const ops = {
[COMMANDS.AND](lookup, l, r) {
return lookup(l) & lookup(r);
},
[COMMANDS.OR](lookup, l, r) {
return lookup(l) | lookup(r);
},
[COMMANDS.LSHIFT](lookup, l, r) {
return lookup(l) << BigInt(r);
},
[COMMANDS.RSHIFT](lookup, l, r) {
return lookup(l) >> BigInt(r);
},
[COMMANDS.NOT](lookup, v) {
return lookup(v) ^ 65535n;
},
[COMMANDS._NO_OP](lookup, v) {
return lookup(v);
},
};
const makeLookup = (input) => {
const lookup = fn.memo((v) => {
if (v.match(/^\d+$/)) {
return BigInt(v);
}
if (!input.has(v)) {
throw new Error('invalid lookup');
}
const { command, args } = input.get(v);
return ops[command](lookup, ...args);
});
return lookup;
};
module.exports = {
'1': (input) => {
return makeLookup(parse(input))('a');
},
'2': (input) => {
input = parse(input);
const override = makeLookup(input)('a');
input.set('b', { command: COMMANDS._NO_OP, args: [override.toString(10)] });
return makeLookup(input)('a');
},
};