|
@@ -0,0 +1,145 @@
|
|
|
|
+const fs = require("node:fs");
|
|
|
|
+const Computer = require("../IntComp/Computer");
|
|
|
|
+
|
|
|
|
+/* Set up the computer */
|
|
|
|
+const input = fs.readFileSync("./15/input.dat", "utf8")
|
|
|
|
+ .split(",")
|
|
|
|
+ .map((x) => parseInt(x, 10));
|
|
|
|
+
|
|
|
|
+const droid = new Computer(input);
|
|
|
|
+
|
|
|
|
+/* Set up values for the simulation */
|
|
|
|
+/**
|
|
|
|
+ * Directions the droid can move in
|
|
|
|
+ */
|
|
|
|
+const Directions = {
|
|
|
|
+ NORTH: 1,
|
|
|
|
+ SOUTH: 2,
|
|
|
|
+ EAST: 3,
|
|
|
|
+ WEST: 4,
|
|
|
|
+};
|
|
|
|
+/**
|
|
|
|
+ * Vectorized values for the Directions values
|
|
|
|
+ */
|
|
|
|
+const Vectors = {
|
|
|
|
+ NORTH: 1,
|
|
|
|
+ SOUTH: -1,
|
|
|
|
+ EAST: 1,
|
|
|
|
+ WEST: -1,
|
|
|
|
+};
|
|
|
|
+/**
|
|
|
|
+ * Tile data for rendering the droid's internal map
|
|
|
|
+ */
|
|
|
|
+const mapTiles = {
|
|
|
|
+ WALL: "█",
|
|
|
|
+ EMPTY: ".",
|
|
|
|
+ OXYGEN: "0",
|
|
|
|
+};
|
|
|
|
+/**
|
|
|
|
+ * The current position of the droid
|
|
|
|
+ *
|
|
|
|
+ * X and Y are relative to the droid's position at the start of the
|
|
|
|
+ * simulation.
|
|
|
|
+ */
|
|
|
|
+const droidPosition = {
|
|
|
|
+ x: 0,
|
|
|
|
+ y: 0
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+const droidMap = new Map();
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * Statuses output but the droid
|
|
|
|
+ */
|
|
|
|
+const STATUS = ["NO_MOVEMENT", "MOVEMENT_SUCCESSFUL", "OXYGEN_FOUND"];
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * The last direction we had the droid move in
|
|
|
|
+ */
|
|
|
|
+let lastDirection = Directions.EAST;
|
|
|
|
+/**
|
|
|
|
+ * The last status code output by the droid
|
|
|
|
+ */
|
|
|
|
+let lastSignal = -1;
|
|
|
|
+
|
|
|
|
+let mapLooped = false;
|
|
|
|
+
|
|
|
|
+// Start the droid
|
|
|
|
+droid.Run()
|
|
|
|
+// Continue running of droid
|
|
|
|
+do {
|
|
|
|
+ // Handle input to the droid
|
|
|
|
+ if (droid.awaitingInput) {
|
|
|
|
+ // Get the new direction to move in
|
|
|
|
+ let currDirection = updateMap(lastDirection, lastSignal);
|
|
|
|
+
|
|
|
|
+ droid.Input(currDirection);
|
|
|
|
+ lastDirection = currDirection;
|
|
|
|
+ }
|
|
|
|
+ // Handle the droid's output
|
|
|
|
+ if (droid.HasOutput()) {
|
|
|
|
+ lastSignal = droid.outputValues.pop()
|
|
|
|
+ console.log(STATUS[lastSignal]);
|
|
|
|
+ }
|
|
|
|
+} while (droid.running && !mapLooped);
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * Update the map data and return a new dirction to move in
|
|
|
|
+ *
|
|
|
|
+ * @param {1|2|3|4} lastDirection The last direction the droid moved in
|
|
|
|
+ * @param {0|1|2} lastSignal The last signal output by the droid
|
|
|
|
+ *
|
|
|
|
+ * @returns {1|2|3|4} A new direction for the droid to move in
|
|
|
|
+ */
|
|
|
|
+function updateMap(lastDirection, lastSignal) {
|
|
|
|
+ let newDirection = lastDirection;
|
|
|
|
+ let mapX = droidPosition.x;
|
|
|
|
+ let mapY = droidPosition.y;
|
|
|
|
+ let foundTile = mapTiles.EMPTY;
|
|
|
|
+
|
|
|
|
+ if (lastSignal == 0) {
|
|
|
|
+ if (lastDirection == Directions.EAST) {
|
|
|
|
+ mapX += Vectors.EAST;
|
|
|
|
+ newDirection = Directions.NORTH;
|
|
|
|
+ }
|
|
|
|
+ else if (lastDirection == Directions.NORTH) {
|
|
|
|
+ mapY += Vectors.NORTH;
|
|
|
|
+ newDirection = Directions.WEST;
|
|
|
|
+ }
|
|
|
|
+ else if (lastDirection == Directions.WEST) {
|
|
|
|
+ mapX += Vectors.WEST;
|
|
|
|
+ newDirection = Directions.SOUTH;
|
|
|
|
+ }
|
|
|
|
+ else if (lastDirection == Directions.SOUTH) {
|
|
|
|
+ mapY += Vectors.SOUTH;
|
|
|
|
+ newDirection = Directions.EAST;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ foundTile = mapTiles.WALL;
|
|
|
|
+ }
|
|
|
|
+ else if (lastSignal == 1) {
|
|
|
|
+ if (lastDirection == Directions.EAST) {
|
|
|
|
+ droidPosition.x += Vectors.EAST;
|
|
|
|
+ }
|
|
|
|
+ else if (lastDirection == Directions.NORTH) {
|
|
|
|
+ droidPosition.y += Vectors.NORTH;
|
|
|
|
+ }
|
|
|
|
+ else if (lastDirection == Directions.WEST) {
|
|
|
|
+ droidPosition.x += Vectors.WEST;
|
|
|
|
+ }
|
|
|
|
+ else if (lastDirection == Directions.SOUTH) {
|
|
|
|
+ droidPosition.y += Vectors.SOUTH;
|
|
|
|
+ }
|
|
|
|
+ foundTile = mapTiles.EMPTY;
|
|
|
|
+ }
|
|
|
|
+ else if (lastSignal == 2) {
|
|
|
|
+ foundTile = mapTiles.OXYGEN;
|
|
|
|
+ console.log(STATUS[lastSignal]);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ mapLooped = droidMap.has(`${mapX},${mapY}`) && mapX + mapY != 0;
|
|
|
|
+
|
|
|
|
+ droidMap.set(`${mapX},${mapY}`, foundTile);
|
|
|
|
+
|
|
|
|
+ return newDirection;
|
|
|
|
+}
|