64 lines
1.6 KiB
JavaScript
64 lines
1.6 KiB
JavaScript
const { Glib } = require('../../lib');
|
|
|
|
const parseInstruction = (i) => {
|
|
const [operation, argument] = i.split(' ');
|
|
return { operation, argument: BigInt(argument) };
|
|
};
|
|
|
|
const parse = (input) => Glib.fromLines(input).map(parseInstruction).array;
|
|
|
|
const operations = new Map([
|
|
['nop', (argument, state) => ({})],
|
|
['acc', (argument, { acc }) => ({ acc: acc + argument })],
|
|
['jmp', (argument, { pc }) => ({ pc: pc + argument })],
|
|
]);
|
|
|
|
const step = (state) => {
|
|
const { pc = 0n, program, acc = 0n } = state;
|
|
const { operation, argument } = program[pc];
|
|
|
|
if (!operations.has(operation)) {
|
|
throw new Error('no such operation');
|
|
}
|
|
const newState = operations.get(operation)(argument, state);
|
|
|
|
if (!newState.hasOwnProperty('pc')) {
|
|
newState.pc = pc + 1n;
|
|
}
|
|
|
|
if (!newState.hasOwnProperty('program')) {
|
|
newState.program = program.slice();
|
|
}
|
|
|
|
return { ...state, ...newState };
|
|
};
|
|
|
|
const run = (program) => {
|
|
let state = { pc: 0n, acc: 0n, program };
|
|
const seenInstructions = new Set();
|
|
while (!seenInstructions.has(state.pc) && state.pc < program.length) {
|
|
seenInstructions.add(state.pc);
|
|
state = step(state);
|
|
}
|
|
return state;
|
|
};
|
|
|
|
module.exports = {
|
|
'1': (input) => run(parse(input)).acc,
|
|
'2': (input) => {
|
|
const program = parse(input);
|
|
return program.glib
|
|
.map(({ operation, argument }, i) => {
|
|
const modified = program.slice();
|
|
modified[i] = {
|
|
operation: operation === 'nop' ? 'jmp' : 'nop',
|
|
argument,
|
|
};
|
|
return run(modified);
|
|
})
|
|
.filter(({ pc, program }) => pc === BigInt(program.length))
|
|
.map(({ acc }) => acc)
|
|
.first();
|
|
},
|
|
};
|