-
Notifications
You must be signed in to change notification settings - Fork 16
/
bridge.js
114 lines (94 loc) · 2.6 KB
/
bridge.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
class Component {
constructor([port_a, port_b]) {
this.a = port_a;
this.b = port_b;
}
otherPort(n) {
if (this.a === n) {
return this.b;
} else if (this.b === n) {
return this.a;
} else {
return null;
}
}
has(n) {
return this.a === n || this.b === n;
}
toString() {
return `${this.a}/${this.b}`;
}
sum() {
return this.a + this.b;
}
}
class Bridges {
constructor(components) {
this.components = components.map(c => new Component(c));
const zeros = this.components.filter(c => c.has(0));
const bridges = zeros.map(c => [c]);
this.solutions = bridges.slice(0);
this.buildBridges(bridges, 0);
}
buildBridges(bridges, current_port) {
for (let bridge of bridges) {
// The value `1` in the WeakMap is arbitrary, I only want to use it for the `.has` method later
let using = new WeakMap(bridge.map(c => [c, 1]));
let last_component = bridge[bridge.length - 1];
let new_port = last_component.otherPort(current_port);
let new_bridges = [];
for (let i = 0; i < this.components.length; i++) {
let component = this.components[i];
if (using.has(component)) {
continue;
}
if (component.has(new_port)) {
let new_bridge = bridge.concat(component);
new_bridges.push(new_bridge);
// Save in overall array to view solutions later
this.solutions.push(new_bridge);
}
}
if (new_bridges.length) {
this.buildBridges(new_bridges, new_port);
}
}
return this.solutions;
}
static getSolutionString(solution) {
// Uses `toString` of Connection class
return solution.join('-');
}
static getSolutionScore(solution) {
return solution.map(c => c.sum()).reduce((a, b) => a + b, 0);
}
printSolutions() {
for (let solution of this.solutions) {
console.log(Bridges.getSolutionString(solution));
}
}
getBestSolution(solutions = this.solutions) {
let best_solution = -1;
let best_solution_index = null;
for (let i = 0; i < solutions.length; i++) {
let solution = solutions[i];
let solution_score = Bridges.getSolutionScore(solution);
if (solution_score > best_solution) {
best_solution = solution_score;
best_solution_index = i;
}
}
return solutions[best_solution_index];
}
getLongestAndHighestScoringBridge() {
// The `Math.max` gives a 'call stack exceeded' error. ¯\_(ツ)_/¯
// let max_length = Math.max(...this.solutions.map(b => b.length));
let max_length = this.solutions
.map(b => b.length)
.sort((a, b) => a - b)
.pop();
let longest_bridges = this.solutions.filter(b => b.length === max_length);
return this.getBestSolution(longest_bridges);
}
}
module.exports = Bridges;