Computer.js 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. const Stack = require("./Stack");
  2. /**
  3. * An Intcode Computer for the Advent of Code 2019 challenge
  4. *
  5. * @author Apis Necros
  6. */
  7. module.exports = class Computer {
  8. constructor(stack) {
  9. this.stack = new Stack(stack);
  10. this.OPCODES = {
  11. ADD: 1,
  12. MULTIPLY: 2,
  13. HALT: 99,
  14. };
  15. this.PARAMETER_MODES = {
  16. POSITION_MODE: 0,
  17. IMMEDIATE_MODE: 1,
  18. }
  19. this.paramMode = this.PARAMETER_MODES.POSITION_MODE;
  20. }
  21. /**
  22. * Run the computer
  23. *
  24. * Runs opcodes on the stack until either the a HALT command is
  25. * encountered, or an error is thrown.
  26. * @returns {void}
  27. */
  28. Run() {
  29. // eslint-disable-next-line no-empty
  30. while (this.Execute(this.stack.Get()) === true) { }
  31. }
  32. /**
  33. * Execute a call using the provided opcode
  34. *
  35. * @param {number} opcode A opcode to execute
  36. * @returns {boolean} False if the opcode was HALT, otherwise true
  37. */
  38. Execute(opcode) {
  39. // console.log(`DEBUG: opcode: ${opcode}`)
  40. let status = true;
  41. switch (opcode) {
  42. case this.OPCODES.ADD: {
  43. const operandLeft = this.stack.Next().GetUsingStackValue();
  44. const operandRight = this.stack.Next().GetUsingStackValue();
  45. const position = this.stack.Next().Get();
  46. this.Operation_Add(operandLeft, operandRight, position);
  47. break;
  48. }
  49. case this.OPCODES.MULTIPLY: {
  50. const operandLeft = this.stack.Next().GetUsingStackValue();
  51. const operandRight = this.stack.Next().GetUsingStackValue();
  52. const position = this.stack.Next().Get();
  53. this.Operation_Multiply(operandLeft, operandRight, position);
  54. break;
  55. }
  56. case this.OPCODES.HALT:
  57. status = false;
  58. break;
  59. default:
  60. throw Error(`Opcode ${opcode} not found`);
  61. }
  62. this.stack.Next();
  63. return status;
  64. }
  65. /**
  66. * Execute the Add opcode
  67. *
  68. * Adds two numbers and stores the result at the provided position
  69. * on the stack.
  70. *
  71. * @param {number} operandLeft The first operand
  72. * @param {number} operandRight The second operand
  73. * @param {number} outputPosition The position on the stack to place the result
  74. * @returns {void}
  75. */
  76. Operation_Add(operandLeft, operandRight, outputPosition) {
  77. const newValue = operandLeft + operandRight;
  78. this.stack.Put(outputPosition, newValue);
  79. }
  80. /**
  81. * Execute the Multiply opcode
  82. *
  83. * Multiplies two numbers and stores the result at the provided
  84. * position on the stack.
  85. *
  86. * @param {number} operandLeft The first operand
  87. * @param {number} operandRight The second operand
  88. * @param {number} outputPosition The position on the stack to place the result
  89. * @returns {void}
  90. */
  91. Operation_Multiply(operandLeft, operandRight, outputPosition) {
  92. const newValue = operandLeft * operandRight;
  93. this.stack.Put(outputPosition, newValue);
  94. }
  95. /**
  96. * Outputs the computer's stack to the console
  97. * @returns {void}
  98. */
  99. DumpMemory() {
  100. console.log(this.stack.Dump());
  101. }
  102. };