-
Notifications
You must be signed in to change notification settings - Fork 17
/
part-two.js
82 lines (65 loc) · 2.15 KB
/
part-two.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
const { input } = require('./input');
const { InfiniteGrid } = require('./infinite-grid');
// Getting fancy / terse here, see part one for a more reasonable way to write these
const sortTopToBottomLeftToRight = ({ coords: ac }, { coords: bc }) =>
ac[1] !== bc[1] ? ac[1] - bc[1] : ac[0] - bc[0];
const sortBottomToTopLeftToRight = ({ coords: ac }, { coords: bc }) =>
ac[1] !== bc[1] ? bc[1] - ac[1] : ac[0] - bc[0];
const sortLeftToRightToptoBottom = ({ coords: ac }, { coords: bc }) =>
ac[0] !== bc[0] ? ac[0] - bc[0] : ac[1] - bc[1];
const sortRightToLeftToptoBottom = ({ coords: ac }, { coords: bc }) =>
ac[0] !== bc[0] ? bc[0] - ac[0] : ac[1] - bc[1];
const spinCycles = [
['N', sortTopToBottomLeftToRight],
['W', sortLeftToRightToptoBottom],
['S', sortBottomToTopLeftToRight],
['E', sortRightToLeftToptoBottom],
];
const EMPTY = '.';
const grid = new InfiniteGrid({ load: input });
const roundRocks = grid.findAll('O');
let foundCycle = false;
let cycle = 0;
const seenGrids = new Set();
function runCycle() {
cycle++;
for (let [dir, sortFn] of spinCycles) {
roundRocks.sort(sortFn);
for (let rock of roundRocks) {
let [x, y] = rock.coords;
while (grid.getNeighbor(x, y, dir)?.[0] === EMPTY) {
// Update x values without updating `rock` (just yet)
[x, y] = grid.moveViaSwap(x, y, dir);
}
// Update our coord reference so we don't have to continuously grab it from the `grid`
rock.coords[0] = x;
rock.coords[1] = y;
}
}
const gridStr = grid.toString();
if (seenGrids.has(gridStr)) {
foundCycle = true;
} else {
seenGrids.add(gridStr);
}
}
while (!foundCycle) {
runCycle();
}
// Cycles are cyclic but in some period - determine the period now that we've seen a previous state (have entered a stable period somewhere)
const periodicStates = [];
do {
periodicStates.push(grid.toString());
runCycle();
} while (!periodicStates.includes(grid.toString()));
const cyclesLeft = (1000000000 - cycle) % periodicStates.length;
for (let i = 0; i < cyclesLeft; i++) {
runCycle();
}
const totalLoad = grid
.findAll('O')
.map(({ coords }) => {
return grid.max_y + 1 - coords[1];
})
.reduce((a, b) => a + b, 0);
console.log(totalLoad);