-
Notifications
You must be signed in to change notification settings - Fork 17
/
Copy pathgrid.js
69 lines (54 loc) · 2.09 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
const G = require('generatorics');
const PF = require('pathfinding');
class Grid {
constructor(grid_str) {
const grid_str_arr = grid_str.split('\n').map(row => row.split(''));
this.grid_arr = grid_str_arr.map(row => row.map(v => (v === '#' ? 1 : 0)));
this.grid = new PF.Grid(this.grid_arr);
this.visits = {};
for (let y = 0; y < grid_str_arr.length; y++) {
const row = grid_str_arr[y];
for (let x = 0; x < row.length; x++) {
const cell = row[x];
if (cell !== '#' && cell !== '.') {
const index = parseInt(cell);
this.visits[index] = [x, y];
}
}
}
}
calculateShortestPathBetweenAllLocations(return_to_start = false) {
// Get all locations minus the starting one
const visits_arr = Object.keys(this.visits).map(v => parseInt(v)).filter(v => v !== 0);
const permutations_without_start = G.clone.permutation(visits_arr);
let possible_paths = [...permutations_without_start];
// Add 0 to start of all paths
possible_paths = possible_paths.map(path => [0].concat(path));
if (return_to_start) {
// End back at 0
possible_paths = possible_paths.map(path => path.concat(0));
}
// Loop through all paths, compute distance between each point, and record those lengths
const possible_distances = possible_paths.map(path => {
// @note
// > Be aware that grid will be modified in each path-finding, and will not be usable afterwards.
// > If you want to use a single grid multiple times, create a clone for it before calling findPath.
let total_distance = 0;
for (let i = 0; i < path.length - 1; i++) {
const spot_1 = path[i];
const spot_2 = path[i + 1];
const [x_1, y_1] = this.visits[spot_1];
const [x_2, y_2] = this.visits[spot_2];
const finder = new PF.AStarFinder();
const grid = this.grid.clone();
const complete_path = finder.findPath(x_1, y_1, x_2, y_2, grid);
// Path includes starting point, which we don't want to count
const distance = complete_path.length - 1;
total_distance += distance;
}
return total_distance;
});
return Math.min(...possible_distances);
}
}
module.exports = Grid;