17 Commits 0f9fdf19b8 ... 7c807aa864

Autor SHA1 Mensagem Data
  ApisNecros 7c807aa864 Add initial attempt at day 12 pt 2 há 4 meses atrás
  ApisNecros 98e4a2fe47 Add check for reaching initial state há 4 meses atrás
  ApisNecros b7ba9471a0 Add initialPosition property to moons há 4 meses atrás
  ApisNecros 4318a7037f Remove commented out line há 4 meses atrás
  ApisNecros ea93be5667 Move common functions into separate file há 4 meses atrás
  ApisNecros b2e5ae02a9 Add day 12 pt 1 solution há 4 meses atrás
  ApisNecros ad13d63d54 Update negate to return a new Vector3 há 4 meses atrás
  ApisNecros 76603389a4 Update calculateGravity to work with Moon class há 4 meses atrás
  ApisNecros c16149a101 Parse input at the start há 4 meses atrás
  ApisNecros 444c7ac5af Add test input há 4 meses atrás
  ApisNecros af3665bbaf Update parseInput to return array of Moons há 4 meses atrás
  ApisNecros c0316de99c Add Moon class há 4 meses atrás
  ApisNecros befb2d7123 Add negate function to Vector3 há 4 meses atrás
  ApisNecros b79a809901 Move Vector3 class to its own file há 4 meses atrás
  ApisNecros 5581773c3f Add function to parse the day's input há 4 meses atrás
  ApisNecros 7f676806ea Add function to calculate gravity between two bodies há 4 meses atrás
  ApisNecros 6ad83a5ed1 Add day's input há 4 meses atrás
5 ficheiros alterados com 246 adições e 31 exclusões
  1. 36 31
      12/12_1.js
  2. 61 0
      12/12_2.js
  3. 42 0
      12/Moon.js
  4. 39 0
      12/Vector3.js
  5. 68 0
      12/common.js

+ 36 - 31
12/12_1.js

@@ -1,40 +1,45 @@
+const Moon = require("./Moon");
+const { step, parseInput } = require("./common");
 
+const input = parseInput([
+    "<x=14, y=15, z=-2>",
+    "<x=17, y=-3, z=4>",
+    "<x=6, y=12, z=-13>",
+    "<x=-2, y=10, z=-8>",
+]);
 
-class Vector3 {
-    /**
-     * A 3D vector
-     *
-     * @param {number} x The X value of this vector
-     * @param {number} y The Y value of this vector
-     * @param {number} z The Z value of this vector
-     */
-    constructor(x, y, z) {
-        this.x = x;
-        this.y = y;
-        this.z = z;
-    }
+const tests = parseInput([
+    "<x=-1, y=0, z=2>",
+    "<x=2, y=-10, z=-7>",
+    "<x=4, y=-8, z=8>",
+    "<x=3, y=5, z=-1>",
+]);
 
-    /**
-     * Add another vector to this one
-     *
-     * @param {Vector3} operand The vector to add to this one
-     * @returns {void}
-     */
-    add(operand) {
-        this.x += operand.x;
-        this.y += operand.y;
-        this.z += operand.z;
-    }
+const STEPS = 1000;
+
+for (let i = 0; i < STEPS; i++) {
+    step(input);
 }
 
+console.log(`Total energy in system is: ${calculateTotalEnergy(input)}`);
+
 /**
- * Find the gravitational influence two moons have on each other
+ * Calculate the total energy in the system
  *
- * @param {Vector3} moonA The first moon to consider
- * @param {Vector3} moonB The second moon to consider
+ * The total energy in the system is the sum of the sum of the positional
+ * values multiplied by the sum of the velocity values.
  *
- * @returns {void}
+ * @param {Moon[]} moons The moons in the system
+ * @returns {number} The total energy in the system
  */
-function calculateGravity(moonA, moonB) {
-    
-}
+function calculateTotalEnergy(moons) {
+    let energy = 0;
+
+    for (const moon of moons) {
+        const potentialEnergy = Math.abs(moon.position.x) + Math.abs(moon.position.y) + Math.abs(moon.position.z);
+        const kineticEnergy = Math.abs(moon.velocity.x) + Math.abs(moon.velocity.y) + Math.abs(moon.velocity.z);
+        energy += potentialEnergy * kineticEnergy;
+    }
+
+    return energy;
+}

+ 61 - 0
12/12_2.js

@@ -0,0 +1,61 @@
+const Moon = require("./Moon");
+const { step, parseInput } = require("./common");
+
+const input = parseInput([
+    "<x=14, y=15, z=-2>",
+    "<x=17, y=-3, z=4>",
+    "<x=6, y=12, z=-13>",
+    "<x=-2, y=10, z=-8>",
+]);
+
+// const tests = parseInput([
+//     "<x=-1, y=0, z=2>",
+//     "<x=2, y=-10, z=-7>",
+//     "<x=4, y=-8, z=8>",
+//     "<x=3, y=5, z=-1>",
+// ]);
+
+const tests = parseInput([
+    "<x=-8, y=-10, z=0>",
+    "<x=5, y=5, z=10>",
+    "<x=2, y=-7, z=3>",
+    "<x=9, y=-8, z=-3>",
+]);
+
+const moons = input;
+
+/**
+ * The amount of steps it takes for a moon to reach its initial state
+ *
+ * Each index in this array corresponds to the index moon in the input.
+ */
+const stepsToLoop = [0, 0, 0, 0];
+let loopsFound = 0;
+
+do {
+    step(moons);
+
+    if ((loopsFound & 1) == 0) {
+        if (moons[0].hasReachedInitialState()) { loopsFound += 1; }
+        stepsToLoop[0]++;
+    }
+
+    if ((loopsFound & 2) == 0) {
+        if (moons[1].hasReachedInitialState()) { loopsFound += 2; }
+        stepsToLoop[1]++;
+    }
+
+    if ((loopsFound & 4) == 0) {
+        if (moons[2].hasReachedInitialState()) { loopsFound += 4; }
+        stepsToLoop[2]++;
+    }
+
+    if ((loopsFound & 8) == 0) {
+        if (moons[3].hasReachedInitialState()) { loopsFound += 8; }
+        stepsToLoop[3]++;
+    }
+} while (loopsFound != 15);
+
+console.log(stepsToLoop);
+
+// console.log(`Steps required to loop: ${steps}`);

+ 42 - 0
12/Moon.js

@@ -0,0 +1,42 @@
+const Vector3 = require("./Vector3");
+
+module.exports = class Moon {
+    /**
+     * @param {Vector3} position The starting position of the moon
+     */
+    constructor(position) {
+        /**
+         * The position of the moon in space
+         */
+        this.position = position;
+        /**
+         * The position of the moon at the time of creation
+         *
+         * This is a silly trick to get a clean copy of the Vector, but it works.
+         *
+         * @private
+         */
+        this._initialPosition = position.negate().negate();
+        /**
+         * The current velocity of the moon
+         */
+        this.velocity = new Vector3(0, 0, 0);
+    }
+
+    /**
+     * Check whether or not the moon has returned to its initial position
+     *
+     * @returns {bool} True if the current position is the same as the initial position and if the velocity is zero
+     */
+    hasReachedInitialState() {
+        return (
+            this._initialPosition.x == this.position.x
+            && this._initialPosition.y == this.position.y
+            && this._initialPosition.z == this.position.z
+        ) && (
+            this.velocity.x == 0
+            && this.velocity.y == 0
+            && this.velocity.z == 0
+        );
+    }
+};

+ 39 - 0
12/Vector3.js

@@ -0,0 +1,39 @@
+module.exports = class Vector3 {
+    /**
+     * A 3D vector
+     *
+     * @param {number} x The X value of this vector
+     * @param {number} y The Y value of this vector
+     * @param {number} z The Z value of this vector
+     */
+    constructor(x, y, z) {
+        this.x = x;
+        this.y = y;
+        this.z = z;
+    }
+
+    /**
+     * Add another vector to this one
+     *
+     * @param {Vector3} operand The vector to add to this one
+     * @returns {void}
+     */
+    add(operand) {
+        this.x += operand.x;
+        this.y += operand.y;
+        this.z += operand.z;
+    }
+
+    /**
+     * Flip the sign of all properties of the vector
+     *
+     * @returns {Vector3} A new Vector3
+     */
+    negate() {
+        return new Vector3(
+            -this.x,
+            -this.y,
+            -this.z,
+        );
+    }
+};

+ 68 - 0
12/common.js

@@ -0,0 +1,68 @@
+const Moon = require("./Moon");
+const Vector3 = require("./Vector3");
+
+/**
+ * @param {string[]} inputs The day's input
+ * @returns {Moon[]} An array of Moon objects
+ */
+function parseInput(inputs) {
+    const moons = [];
+    const parseRegex = new RegExp(/x=(-?\d+), y=(-?\d+), z=(-?\d+)/);
+
+    for (const position of inputs) {
+        // eslint-disable-next-line no-shadow-restricted-names
+        const [undefined, x, y, z] = position.match(parseRegex);
+        moons.push(new Moon(new Vector3(parseInt(x, 10), parseInt(y, 10), parseInt(z, 10))));
+    }
+
+    return moons;
+}
+
+/**
+ * Calculate one step of time
+ *
+ * @param {Moon[]} moons A list of moons
+ * @returns {void}
+ */
+function step(moons) {
+    for (let i = 0; i < moons.length - 1; i++) {
+        for (let j = i + 1; j < moons.length; j++) {
+            // Calculate Moon B's gravity influence on Moon A
+            const firstGravity = calculateGravity(moons[i], moons[j]);
+            // Invert the signage to represent Moon A's influence on Moon B
+            const secondGravity = firstGravity.negate();
+
+            moons[i].velocity.add(firstGravity);
+            moons[j].velocity.add(secondGravity);
+        }
+    }
+
+    moons.forEach((moon) => { moon.position.add(moon.velocity); });
+}
+
+/**
+ * Find the gravitational influence two moons have on each other
+ *
+ * @param {Moon} moonA The first moon to consider
+ * @param {Moon} moonB The second moon to consider
+ *
+ * @returns {Vector3} The gravitational influence of Moon B on Moon A
+ */
+function calculateGravity(moonA, moonB) {
+    // The gravitational pull on Moon A caused by Moon B
+    const gravityDifference = new Vector3(
+        // eslint-disable-next-line no-nested-ternary
+        moonB.position.x > moonA.position.x ? 1 : (moonB.position.x < moonA.position.x ? -1 : 0),
+        // eslint-disable-next-line no-nested-ternary
+        moonB.position.y > moonA.position.y ? 1 : (moonB.position.y < moonA.position.y ? -1 : 0),
+        // eslint-disable-next-line no-nested-ternary
+        moonB.position.z > moonA.position.z ? 1 : (moonB.position.z < moonA.position.z ? -1 : 0),
+    );
+
+    return gravityDifference;
+}
+
+module.exports = {
+    parseInput,
+    step,
+};