-
Notifications
You must be signed in to change notification settings - Fork 0
/
day12.js
129 lines (103 loc) · 3.28 KB
/
day12.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
const fs = require('fs');
const math = require('math');
const main = async () => {
const input = fs.readFileSync('day12input.txt').toString();
const lines = input.split('\n');
const moons = [];
let id = 0;
for (const line of lines) {
const position = [];
const items = line.replace('<', '')
.replace('>', '')
.split(', ');
for (const item of items) {
position.push(item.split('=')[1]);
}
moons.push({ id, point: position, velocity: [0, 0, 0] });
id++;
}
const cyclePoint = getCyclePoint(moons);
cyclePoint.found = {};
let keepCycling = true;
let iteration = 1;
while (keepCycling) {
iteration++;
applyGravity(moons);
applyVelocity(moons);
checkIfAtCyclePoint(cyclePoint, moons, iteration);
keepCycling = !allCycleTimesFound(cyclePoint);
}
const finalValue = lcm(cyclePoint.found[2], lcm(cyclePoint.found[1], cyclePoint.found[0]));
console.log(finalValue);
}
const getCyclePoint = (positions) => {
const cyclePoint = { 0: [], 1: [], 2: []};
for (const item of positions) {
cyclePoint[Number(0)].push(Number(item.point[0]));
cyclePoint[Number(1)].push(Number(item.point[1]));
cyclePoint[Number(2)].push(Number(item.point[2]));
}
return cyclePoint;
}
const checkIfEqual = (aItems, bItems) => {
const equal = JSON.stringify(aItems) === JSON.stringify(bItems);
return equal;
}
const calculateEnergy = (items) => {
let energy = 0;
for (const item of items) {
const potential = Number(Math.abs(item.point[0]) + Math.abs(item.point[1]) + Math.abs(item.point[2]));
const kinetic = Number(Math.abs(item.velocity[0]) + Math.abs(item.velocity[1]) + Math.abs(item.velocity[2]));
energy = energy + kinetic * potential;
}
return energy;
}
const allCycleTimesFound = cyclePoint => {
return Object.keys(cyclePoint.found).length === 3
}
const checkIfAtCyclePoint = (cyclePoint, items, iteration) => {
const newCyclePoint = getCyclePoint(items);
const keys = Object.keys(newCyclePoint);
for (const key of keys) {
if (!cyclePoint.found[key] && checkIfEqual(cyclePoint[key], newCyclePoint[key])) {
cyclePoint.found[key] = iteration;
}
}
}
const applyVelocity = (items) => {
for (const item of items) {
item.point[0] = Number(item.point[0]) + Number(item.velocity[0]);
item.point[1] = Number(item.point[1]) + Number(item.velocity[1]);
item.point[2] = Number(item.point[2]) + Number(item.velocity[2]);
}
}
const lcm = (a, b) => {
return (Number(a) * Number(b)) / math.gcd(a, b)
}
const applyGravity = (items) => {
for (const item of items) {
updateOneGravity(item, items);
}
return items;
}
const updateOneGravity = (point, items) => {
for (const item of items) {
if (point.id === item.id) continue;
updateOneCoordinate(point, item, 0);
updateOneCoordinate(point, item, 1);
updateOneCoordinate(point, item, 2);
}
};
const updateOneCoordinate = (a, b, index) => {
if (a.point[index] !== b.point[index]) {
const onePosition = Number(a.point[index]);
const twoPosition = Number(b.point[index]);
// move each gravity one closer to the other one
if (onePosition < twoPosition) {
a.velocity[index] = a.velocity[index] + 1;
} else if (onePosition > twoPosition) {
a.velocity[index] = a.velocity[index] - 1;
}
}
}
main();