Computer.js 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  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. OUTPUT: 4,
  14. HALT: 99,
  15. };
  16. this.PARAMETER_MODES = {
  17. POSITION_MODE: 0,
  18. IMMEDIATE_MODE: 1,
  19. }
  20. this.paramMode = this.PARAMETER_MODES.POSITION_MODE;
  21. }
  22. /**
  23. * Run the computer
  24. *
  25. * Runs opcodes on the stack until either the a HALT command is
  26. * encountered, or an error is thrown.
  27. * @returns {void}
  28. */
  29. Run() {
  30. // eslint-disable-next-line no-empty
  31. while (this.Execute(this.stack.Get()) === true) { }
  32. }
  33. /**
  34. * Execute a call using the provided opcode
  35. *
  36. * @param {number} opcode A opcode to execute
  37. * @returns {boolean} False if the opcode was HALT, otherwise true
  38. */
  39. Execute(opcode) {
  40. // console.log(`DEBUG: opcode: ${opcode}`)
  41. let status = true;
  42. switch (opcode) {
  43. case this.OPCODES.ADD: {
  44. const operandLeft = this.stack.Next().GetUsingStackValue();
  45. const operandRight = this.stack.Next().GetUsingStackValue();
  46. const position = this.stack.Next().Get();
  47. this.Operation_Add(operandLeft, operandRight, position);
  48. break;
  49. }
  50. case this.OPCODES.MULTIPLY: {
  51. const operandLeft = this.stack.Next().GetUsingStackValue();
  52. const operandRight = this.stack.Next().GetUsingStackValue();
  53. const position = this.stack.Next().Get();
  54. this.Operation_Multiply(operandLeft, operandRight, position);
  55. break;
  56. }
  57. case this.OPCODES.OUTPUT: {
  58. const outputPosition = this.stack.Next().Get();
  59. this.Operation_Output(outputPosition);
  60. }
  61. case this.OPCODES.HALT:
  62. status = false;
  63. break;
  64. default:
  65. throw Error(`Opcode ${opcode} not found`);
  66. }
  67. this.stack.Next();
  68. return status;
  69. }
  70. /**
  71. * Execute the Add opcode
  72. *
  73. * Adds two numbers and stores the result at the provided position
  74. * on the stack.
  75. *
  76. * @param {number} operandLeft The first operand
  77. * @param {number} operandRight The second operand
  78. * @param {number} outputPosition The position on the stack to place the result
  79. * @returns {void}
  80. */
  81. Operation_Add(operandLeft, operandRight, outputPosition) {
  82. const newValue = operandLeft + operandRight;
  83. this.stack.Put(outputPosition, newValue);
  84. }
  85. /**
  86. * Execute the Multiply opcode
  87. *
  88. * Multiplies two numbers and stores the result at the provided
  89. * position on the stack.
  90. *
  91. * @param {number} operandLeft The first operand
  92. * @param {number} operandRight The second operand
  93. * @param {number} outputPosition The position on the stack to place the result
  94. * @returns {void}
  95. */
  96. Operation_Multiply(operandLeft, operandRight, outputPosition) {
  97. const newValue = operandLeft * operandRight;
  98. this.stack.Put(outputPosition, newValue);
  99. }
  100. /**
  101. * Execute the OUTPUT opcode
  102. *
  103. * @param {number} outputPosition The memory address of the value to output
  104. */
  105. Operation_Output(outputPosition) {
  106. console.log(this.stack.Get(outputPosition));
  107. }
  108. /**
  109. * Outputs the computer's stack to the console
  110. * @returns {void}
  111. */
  112. DumpMemory() {
  113. console.log(this.stack.Dump());
  114. }
  115. };