12_1.js 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. const util = require("util");
  2. const Vector3 = require("./Vector3");
  3. const Moon = require("./Moon");
  4. const input = parseInput([
  5. "<x=14, y=15, z=-2>",
  6. "<x=17, y=-3, z=4>",
  7. "<x=6, y=12, z=-13>",
  8. "<x=-2, y=10, z=-8>",
  9. ]);
  10. const tests = parseInput([
  11. "<x=-1, y=0, z=2>",
  12. "<x=2, y=-10, z=-7>",
  13. "<x=4, y=-8, z=8>",
  14. "<x=3, y=5, z=-1>",
  15. ]);
  16. const STEPS = 1000;
  17. for (let i = 0; i < STEPS; i++) {
  18. step(input);
  19. }
  20. console.log(`Total energy in system is: ${calculateTotalEnergy(input)}`);
  21. /**
  22. * Calculate one step of time
  23. *
  24. * @param {Moon[]} moons A list of moons
  25. * @returns {void}
  26. */
  27. function step(moons) {
  28. for (let i = 0; i < moons.length - 1; i++) {
  29. for (let j = i + 1; j < moons.length; j++) {
  30. // Calculate Moon B's gravity influence on Moon A
  31. const firstGravity = calculateGravity(moons[i], moons[j]);
  32. // Invert the signage to represent Moon A's influence on Moon B
  33. const secondGravity = firstGravity.negate();
  34. moons[i].velocity.add(firstGravity);
  35. moons[j].velocity.add(secondGravity);
  36. }
  37. }
  38. moons.forEach((moon) => { moon.position.add(moon.velocity); });
  39. }
  40. /**
  41. * Find the gravitational influence two moons have on each other
  42. *
  43. * @param {Moon} moonA The first moon to consider
  44. * @param {Moon} moonB The second moon to consider
  45. *
  46. * @returns {Vector3} The gravitational influence of Moon B on Moon A
  47. */
  48. function calculateGravity(moonA, moonB) {
  49. // The gravitational pull on Moon A caused by Moon B
  50. const gravityDifference = new Vector3(
  51. // eslint-disable-next-line no-nested-ternary
  52. moonB.position.x > moonA.position.x ? 1 : (moonB.position.x < moonA.position.x ? -1 : 0),
  53. // eslint-disable-next-line no-nested-ternary
  54. moonB.position.y > moonA.position.y ? 1 : (moonB.position.y < moonA.position.y ? -1 : 0),
  55. // eslint-disable-next-line no-nested-ternary
  56. moonB.position.z > moonA.position.z ? 1 : (moonB.position.z < moonA.position.z ? -1 : 0),
  57. );
  58. return gravityDifference;
  59. }
  60. /**
  61. * Calculate the total energy in the system
  62. *
  63. * The total energy in the system is the sum of the sum of the positional
  64. * values multiplied by the sum of the velocity values.
  65. *
  66. * @param {Moon[]} moons The moons in the system
  67. * @returns {number} The total energy in the system
  68. */
  69. function calculateTotalEnergy(moons) {
  70. let energy = 0;
  71. for (const moon of moons) {
  72. const potentialEnergy = Math.abs(moon.position.x) + Math.abs(moon.position.y) + Math.abs(moon.position.z);
  73. const kineticEnergy = Math.abs(moon.velocity.x) + Math.abs(moon.velocity.y) + Math.abs(moon.velocity.z);
  74. energy += potentialEnergy * kineticEnergy;
  75. }
  76. return energy;
  77. }
  78. /**
  79. * @param {string[]} inputs The day's input
  80. * @returns {Moon[]} An array of Moon objects
  81. */
  82. function parseInput(inputs) {
  83. const moons = [];
  84. const parseRegex = new RegExp(/x=(-?\d+), y=(-?\d+), z=(-?\d+)/);
  85. for (const position of inputs) {
  86. // eslint-disable-next-line no-shadow-restricted-names
  87. const [undefined, x, y, z] = position.match(parseRegex);
  88. moons.push(new Moon(new Vector3(parseInt(x, 10), parseInt(y, 10), parseInt(z, 10))));
  89. }
  90. return moons;
  91. }
  92. // console.log(util.inspect(parseInput(input)));