const Stack = require("./Stack"); /** * An Intcode Computer for the Advent of Code 2019 challenge * * @author Apis Necros */ module.exports = class Computer { constructor(stack) { this.stack = new Stack(stack); this.OPCODES = { ADD: 1, MULTIPLY: 2, HALT: 99, }; } /** * Run the computer * * Runs opcodes on the stack until either the a HALT command is * encountered, or an error is thrown. * @returns {void} */ Run() { // eslint-disable-next-line no-empty while (this.Execute(this.stack.Get()) === true) { } } /** * Execute a call using the provided opcode * * @param {number} opcode A opcode to execute * @returns {boolean} False if the opcode was HALT, otherwise true */ Execute(opcode) { // console.log(`DEBUG: opcode: ${opcode}`) let status = true; switch (opcode) { case this.OPCODES.ADD: { const operandLeft = this.stack.Next().GetUsingStackValue(); const operandRight = this.stack.Next().GetUsingStackValue(); const position = this.stack.Next().Get(); this.Operation_Add(operandLeft, operandRight, position); break; } case this.OPCODES.MULTIPLY: { const operandLeft = this.stack.Next().GetUsingStackValue(); const operandRight = this.stack.Next().GetUsingStackValue(); const position = this.stack.Next().Get(); this.Operation_Multiply(operandLeft, operandRight, position); break; } case this.OPCODES.HALT: status = false; break; default: throw Error(`Opcode ${opcode} not found`); } this.stack.Next(); return status; } /** * Execute the Add opcode * * Adds two numbers and stores the result at the provided position * on the stack. * * @param {number} operandLeft The first operand * @param {number} operandRight The second operand * @param {number} outputPosition The position on the stack to place the result * @returns {void} */ Operation_Add(operandLeft, operandRight, outputPosition) { const newValue = operandLeft + operandRight; this.stack.Put(outputPosition, newValue); } /** * Execute the Multiply opcode * * Multiplies two numbers and stores the result at the provided * position on the stack. * * @param {number} operandLeft The first operand * @param {number} operandRight The second operand * @param {number} outputPosition The position on the stack to place the result * @returns {void} */ Operation_Multiply(operandLeft, operandRight, outputPosition) { const newValue = operandLeft * operandRight; this.stack.Put(outputPosition, newValue); } /** * Outputs the computer's stack to the console * @returns {void} */ DumpMemory() { console.log(this.stack.Dump()); } };