-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathpart2.ts
64 lines (57 loc) · 2.58 KB
/
part2.ts
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
import * as fs from 'fs';
const input = fs.readFileSync('input', 'utf8').split('\n');
const hailstones = [];
const velocities = [{}, {}, {}];
for (const line of input) {
const [position, velocity] = line.split(' @ ').map((x) => x.split(', ').map(Number));
velocities[0][velocity[0]] ??= [];
velocities[0][velocity[0]].push(position[0]);
velocities[1][velocity[1]] ??= [];
velocities[1][velocity[1]].push(position[1]);
velocities[2][velocity[2]] ??= [];
velocities[2][velocity[2]].push(position[2]);
hailstones.push([position, velocity]);
}
// Assuming nanosecond is the smallest time unit, and all collisions happen in a integer of nanosecond.
// We can get the velocity of the rock, that it can reach the position of each hailstones,
// by keeping the velocity that hailstones offset are divisible by the relative velocity
const rockVelocity = velocities.map((v) => {
const possibleVelocity = Array.from({ length: 2001 }, (_, i) => i - 1000); // [-1000, ..., 1000]
for (const velocity of Object.keys(v)) {
const positions = v[velocity];
if (positions.length < 2) continue; // Only 1 hailstone in this position
const newPossibleVelocity = possibleVelocity.filter(
(x) => (positions[0] - positions[1]) % (x - Number(velocity)) === 0,
);
possibleVelocity.length = 0;
possibleVelocity.push(...newPossibleVelocity);
}
return possibleVelocity[0];
});
const results = {};
for (let i = 0; i < hailstones.length; i++) {
for (let j = i + 1; j < hailstones.length; j++) {
const h1 = hailstones[i];
const h2 = hailstones[j];
// (pxr - px0) / (vx0 - vxr) = (pyr - py0) / (vy0 - vyr)
// (pxr - px0) / (vx0 - vxr) = (pzr - pz0) / (vz0 - vzr)
// (vy1 - vyr) / (vx1 - vxr) ###Q1### = (pyr - py1) / (pxr - px1)
// (vy2 - vyr) / (vx2 - vxr) ###Q2### = (pyr - py2) / (pxr - px2)
// Q1 * (pxr - px1) - Q2 * (pxr - px2) = py2 - py1
// pxr * (Q1 - Q2) + Q2 * px2 - Q1 * px1 = py2 - py1
// pxr = (py2 - py1 - Q2 * px2 - Q1 * px1) / (Q1 - Q2)
// etc...
const quotient1 = (h1[1][1] - rockVelocity[1]) / (h1[1][0] - rockVelocity[0]);
const quotient2 = (h2[1][1] - rockVelocity[1]) / (h2[1][0] - rockVelocity[0]);
const rockX = Math.floor(
(h2[0][1] - quotient2 * h2[0][0] - h1[0][1] + quotient1 * h1[0][0]) / (quotient1 - quotient2),
);
const rockY = Math.floor(quotient1 * rockX + h1[0][1] - quotient1 * h1[0][0]);
const rockZ =
h1[0][2] +
(h1[1][2] - rockVelocity[2]) * Math.round((rockX - h1[0][0]) / (h1[1][0] - rockVelocity[0]));
results[rockX + rockY + rockZ] ??= 0;
results[rockX + rockY + rockZ]++;
}
}
console.log(Object.keys(results).sort((a, b) => results[b] - results[a])[0]);