-
Notifications
You must be signed in to change notification settings - Fork 17
/
Copy pathgrid.js
129 lines (110 loc) · 3.27 KB
/
grid.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 EMPTY = 'L';
const OCCUPIED = '#';
const FLOOR = '.';
class Grid {
constructor(initial_grid_state) {
this.original_grid_str = JSON.stringify(initial_grid_state);
this.grid = JSON.parse(JSON.stringify(initial_grid_state));
}
reset() {
this.grid = JSON.parse(this.original_grid_str);
}
getFirstInDir(values, _x, _y, [h, v]) {
let x = _x + h;
let y = _y + v;
while (this.grid[y] && this.grid[y][x]) {
if (values.includes(this.grid[y][x])) {
return [x, y];
}
x += h;
y += v;
}
return;
}
getVisualNeighbors(x, y) {
// prettier-ignore
return [
this.getFirstInDir([OCCUPIED, EMPTY], x, y, [0, -1]), // top
this.getFirstInDir([OCCUPIED, EMPTY], x, y, [1, -1]), // top right
this.getFirstInDir([OCCUPIED, EMPTY], x, y, [1, 0]), // right
this.getFirstInDir([OCCUPIED, EMPTY], x, y, [1, 1]), // bottom right
this.getFirstInDir([OCCUPIED, EMPTY], x, y, [0, 1]), // bottom
this.getFirstInDir([OCCUPIED, EMPTY], x, y, [-1, 1]), // bottom left
this.getFirstInDir([OCCUPIED, EMPTY], x, y, [-1, 0]), // left
this.getFirstInDir([OCCUPIED, EMPTY], x, y, [-1, -1]), // top left
]
.filter((v) => v)
.filter(([_x, _y]) => typeof (this.grid[_y] && this.grid[_y][_x]) !== 'undefined')
.map(([_x, _y]) => this.grid[_y][_x]);
}
getNeighbors(x, y) {
// prettier-ignore
let neighbors = [
[x, y - 1], // top
[x + 1, y - 1], // top right
[x + 1, y], // right
[x + 1, y + 1], // bottom right
[x, y + 1], // bottom
[x - 1, y + 1], // bottom left
[x - 1, y], // left
[x - 1, y - 1], // top left
].filter(([_x, _y]) => typeof (this.grid[_y] && this.grid[_y][_x]) !== 'undefined');
return neighbors.map(([_x, _y]) => this.grid[_y][_x]);
}
run({ part }) {
let changed;
do {
let new_grid_state = Array(this.grid.length)
.fill()
.map(() => Array(this.grid[0].length).fill());
changed = false;
for (let y = 0; y < this.grid.length; y++) {
for (let x = 0; x < this.grid[0].length; x++) {
let cell = this.grid[y][x];
let neighbors =
part === 1 ? this.getNeighbors(x, y) : this.getVisualNeighbors(x, y);
let occupied_neighbors = 0;
let empty_neighbords = 0;
neighbors.forEach((n) => {
if (n === OCCUPIED) occupied_neighbors++;
else if (n === EMPTY) empty_neighbords++;
});
if (cell === FLOOR) {
new_grid_state[y][x] = FLOOR;
} else if (cell === EMPTY) {
if (occupied_neighbors === 0) {
new_grid_state[y][x] = OCCUPIED;
changed = true;
} else new_grid_state[y][x] = EMPTY;
} else if (cell === OCCUPIED) {
if (occupied_neighbors >= (part === 1 ? 4 : 5)) {
new_grid_state[y][x] = EMPTY;
changed = true;
} else new_grid_state[y][x] = OCCUPIED;
} else {
console.error('err');
}
}
}
// Update our real grid
this.grid = new_grid_state;
} while (changed);
return this.countType();
}
countType(type = OCCUPIED) {
let count = 0;
for (let y = 0; y < this.grid.length; y++) {
for (let x = 0; x < this.grid[0].length; x++) {
if (this.grid[y][x] === type) {
count++;
}
}
}
return count;
}
printGrid() {
let grid_str = this.grid.map((row) => row.join('')).join('\n');
console.log(grid_str + '\n');
}
}
module.exports = { Grid };