11_2.js 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. const util = require("util");
  2. const Computer = require("../IntComp/Computer");
  3. const SpaceImageFormat = require("../SpaceImageFormat/SpaceImageFormat");
  4. const input = [3, 8, 1005, 8, 330, 1106, 0, 11, 0, 0, 0, 104, 1, 104, 0, 3, 8, 102, -1, 8, 10, 101, 1, 10, 10, 4, 10, 1008, 8, 0, 10, 4, 10, 102, 1, 8, 29, 3, 8, 1002, 8, -1, 10, 1001, 10, 1, 10, 4, 10, 1008, 8, 0, 10, 4, 10, 101, 0, 8, 51, 1, 1103, 2, 10, 1006, 0, 94, 1006, 0, 11, 1, 1106, 13, 10, 3, 8, 1002, 8, -1, 10, 101, 1, 10, 10, 4, 10, 1008, 8, 1, 10, 4, 10, 1001, 8, 0, 87, 3, 8, 102, -1, 8, 10, 101, 1, 10, 10, 4, 10, 1008, 8, 0, 10, 4, 10, 1001, 8, 0, 109, 2, 1105, 5, 10, 2, 103, 16, 10, 1, 1103, 12, 10, 2, 105, 2, 10, 3, 8, 102, -1, 8, 10, 1001, 10, 1, 10, 4, 10, 108, 1, 8, 10, 4, 10, 1001, 8, 0, 146, 1006, 0, 49, 2, 1, 12, 10, 2, 1006, 6, 10, 1, 1101, 4, 10, 3, 8, 1002, 8, -1, 10, 1001, 10, 1, 10, 4, 10, 108, 0, 8, 10, 4, 10, 1001, 8, 0, 183, 1, 6, 9, 10, 1006, 0, 32, 3, 8, 102, -1, 8, 10, 1001, 10, 1, 10, 4, 10, 1008, 8, 1, 10, 4, 10, 101, 0, 8, 213, 2, 1101, 9, 10, 3, 8, 1002, 8, -1, 10, 1001, 10, 1, 10, 4, 10, 1008, 8, 1, 10, 4, 10, 101, 0, 8, 239, 1006, 0, 47, 1006, 0, 4, 2, 6, 0, 10, 1006, 0, 58, 3, 8, 1002, 8, -1, 10, 1001, 10, 1, 10, 4, 10, 1008, 8, 0, 10, 4, 10, 102, 1, 8, 274, 2, 1005, 14, 10, 1006, 0, 17, 1, 104, 20, 10, 1006, 0, 28, 3, 8, 102, -1, 8, 10, 1001, 10, 1, 10, 4, 10, 108, 1, 8, 10, 4, 10, 1002, 8, 1, 309, 101, 1, 9, 9, 1007, 9, 928, 10, 1005, 10, 15, 99, 109, 652, 104, 0, 104, 1, 21101, 0, 937263411860, 1, 21102, 347, 1, 0, 1105, 1, 451, 21101, 932440724376, 0, 1, 21102, 1, 358, 0, 1105, 1, 451, 3, 10, 104, 0, 104, 1, 3, 10, 104, 0, 104, 0, 3, 10, 104, 0, 104, 1, 3, 10, 104, 0, 104, 1, 3, 10, 104, 0, 104, 0, 3, 10, 104, 0, 104, 1, 21101, 0, 29015167015, 1, 21101, 0, 405, 0, 1106, 0, 451, 21102, 1, 3422723163, 1, 21101, 0, 416, 0, 1106, 0, 451, 3, 10, 104, 0, 104, 0, 3, 10, 104, 0, 104, 0, 21101, 0, 868389376360, 1, 21101, 0, 439, 0, 1105, 1, 451, 21102, 825544712960, 1, 1, 21102, 1, 450, 0, 1106, 0, 451, 99, 109, 2, 21201, -1, 0, 1, 21101, 0, 40, 2, 21102, 482, 1, 3, 21102, 1, 472, 0, 1106, 0, 515, 109, -2, 2106, 0, 0, 0, 1, 0, 0, 1, 109, 2, 3, 10, 204, -1, 1001, 477, 478, 493, 4, 0, 1001, 477, 1, 477, 108, 4, 477, 10, 1006, 10, 509, 1101, 0, 0, 477, 109, -2, 2106, 0, 0, 0, 109, 4, 2101, 0, -1, 514, 1207, -3, 0, 10, 1006, 10, 532, 21102, 1, 0, -3, 22101, 0, -3, 1, 22102, 1, -2, 2, 21102, 1, 1, 3, 21101, 551, 0, 0, 1106, 0, 556, 109, -4, 2105, 1, 0, 109, 5, 1207, -3, 1, 10, 1006, 10, 579, 2207, -4, -2, 10, 1006, 10, 579, 22102, 1, -4, -4, 1106, 0, 647, 21201, -4, 0, 1, 21201, -3, -1, 2, 21202, -2, 2, 3, 21102, 1, 598, 0, 1106, 0, 556, 22101, 0, 1, -4, 21101, 1, 0, -1, 2207, -4, -2, 10, 1006, 10, 617, 21102, 0, 1, -1, 22202, -2, -1, -2, 2107, 0, -3, 10, 1006, 10, 639, 21201, -1, 0, 1, 21102, 639, 1, 0, 105, 1, 514, 21202, -2, -1, -2, 22201, -4, -2, -4, 109, -5, 2105, 1, 0];
  5. /** All possible vectors for the robot to move */
  6. const Vectors = {
  7. NORTH: {
  8. x: 0,
  9. y: -1,
  10. },
  11. SOUTH: {
  12. x: 0,
  13. y: 1,
  14. },
  15. EAST: {
  16. x: 1,
  17. y: 0,
  18. },
  19. WEST: {
  20. x: -1,
  21. y: 0,
  22. },
  23. };
  24. /**
  25. * Data for tracking the robot's movement
  26. */
  27. const mapData = {
  28. /**
  29. * Tiles we've painted, value is the current color
  30. */
  31. grid: new Map(),
  32. /**
  33. * Unique number of tiles we've painted
  34. */
  35. uniquePaintings: 0,
  36. /**
  37. * The current coordinates of the robot
  38. */
  39. position: {
  40. x: 0,
  41. y: 0,
  42. },
  43. /**
  44. * The current direction the robot is facing
  45. */
  46. vector: Vectors.NORTH,
  47. /**
  48. * Paint the tile below the robot a given color
  49. *
  50. * @param {number} tileColor The new color for the tile below the robot
  51. * @returns {void}
  52. */
  53. PaintTile: function (tileColor) {
  54. const hashMapKey = `${this.position.x},${this.position.y}`;
  55. const uniqueTile = this.grid.get(hashMapKey) === undefined;
  56. this.grid.set(hashMapKey, tileColor);
  57. if (uniqueTile) {
  58. this.uniquePaintings++;
  59. }
  60. },
  61. /**
  62. * Set the heading for the robot
  63. *
  64. * @param {boolean} rotateLeft Should the robot rotate left? If not, rotate right
  65. * @returns {void}
  66. */
  67. SetHeading: function (rotateLeft) {
  68. switch (this.vector) {
  69. case Vectors.NORTH:
  70. // console.log(`DEBUG: Facing North, turning ${rotateLeft ? "West" : "East"}`);
  71. this.vector = rotateLeft ? Vectors.WEST : Vectors.EAST;
  72. break;
  73. case Vectors.SOUTH:
  74. // console.log(`DEBUG: Facing South, turning ${rotateLeft ? "East" : "West"}`);
  75. this.vector = rotateLeft ? Vectors.EAST : Vectors.WEST;
  76. break;
  77. case Vectors.EAST:
  78. // console.log(`DEBUG: Facing West, turning ${rotateLeft ? "North" : "South"}`);
  79. this.vector = rotateLeft ? Vectors.NORTH : Vectors.SOUTH;
  80. break;
  81. case Vectors.WEST:
  82. // console.log(`DEBUG: Facing East, turning ${rotateLeft ? "South" : "North"}`);
  83. this.vector = rotateLeft ? Vectors.SOUTH : Vectors.NORTH;
  84. break;
  85. default:
  86. throw new Error("Wuh?");
  87. }
  88. },
  89. /**
  90. * Move the robot along the current vector
  91. * @returns {void}
  92. */
  93. Move: function () {
  94. this.position.x += this.vector.x;
  95. this.position.y += this.vector.y;
  96. },
  97. };
  98. // Create and run the computer, Robby
  99. const robby = new Computer(input);
  100. robby.Run();
  101. // Start Robby on a white tile
  102. mapData.grid.set("0,0", 1);
  103. // Increase by one to account for previous line
  104. mapData.uniquePaintings++;
  105. let loopCount = 0;
  106. do {
  107. const currentColor = mapData.grid.get(`${mapData.position.x},${mapData.position.y}`) ?? 0;
  108. robby.Input(currentColor);
  109. const nextColor = robby.FetchOutputValue();
  110. const nextRotation = robby.FetchOutputValue();
  111. mapData.SetHeading(nextRotation == 0);
  112. mapData.PaintTile(nextColor);
  113. mapData.Move();
  114. if (++loopCount > 10_000_000) { console.error("Loop went on for too long."); process.exit(0); }
  115. } while (robby.running);
  116. console.log(`Total unique painted tiles: ${mapData.uniquePaintings}`);
  117. // Image data for Registration Identifier
  118. let imageData = [];
  119. // Loop over grid to key coords and their colors
  120. mapData.grid.forEach((color, coords) => {
  121. const [row, column] = coords.split(",");
  122. if (!imageData[column]) { imageData[column] = []; }
  123. imageData[column][row] = color;
  124. });
  125. // Flatten it into one array, and replace undefined's with null's
  126. imageData = imageData.map(fillEmptySlotsWithZero)
  127. .map((row) => { while (row.length < 43) { row.push(0); } return row; })
  128. .flat();
  129. // Join it into a data stream
  130. imageData = imageData.join("");
  131. // Create and render the image
  132. // Height was found from this post: https://old.reddit.com/r/adventofcode/comments/e93d3y/2019_day_11_part_2_animated_python_output/
  133. // Width was brute forced
  134. const height = 6;
  135. const width = 43;
  136. // Render Robby's path as a Space Image
  137. const identifier = new SpaceImageFormat(width, height, imageData);
  138. identifier.Render();
  139. console.log();
  140. /**
  141. * Fill empty slots in an array with zeros
  142. *
  143. * @param {array} arr The array to fill
  144. * @returns {array} The input array with no empty spots
  145. */
  146. function fillEmptySlotsWithZero(arr) {
  147. return Array.from(arr, (_, i) => {
  148. if (!(i in arr)) { return 0; }
  149. return arr[i];
  150. });
  151. }