Skip to content

Commit 8fb6936

Browse files
committed
Added hard/hamiltonian_path
1 parent 83ac1a7 commit 8fb6936

File tree

2 files changed

+158
-0
lines changed

2 files changed

+158
-0
lines changed

hard/hamiltonian_path.js

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
/**
2+
* Using the JavaScript language, have the function hamiltonianPath(strArr) take
3+
* strArr which will be an array of length three. The first part of the array
4+
* will be a list of vertices in a graph in the form (A,B,C,...), the second
5+
* part of the array will be the edges connecting the vertices in the form
6+
* (A-B,C-D,...) where each edge is bidirectional. The last part of the array
7+
* will be a set of vertices in the form (X,Y,Z,...) and your program will have
8+
* to determine whether or not the set of vertices given forms a Hamiltonian
9+
* path on the graph which means that every vertex in the graph is visited only
10+
* once in the order given.
11+
*
12+
* For example: if strArr is ["(A,B,C,D)","(A-B,A-D,B-D,A-C)","(C,A,D,B)"] then
13+
* the vertices (C,A,D,B) in this order do in fact form a Hamiltonian path on
14+
* the graph so your program should return the string yes. If for example the
15+
* last part of the array was (D,A,B,C) then this doesn't form a Hamiltonian
16+
* path because once you get to B you can't get to C in the graph without
17+
* passing through the visited vertices again. Here your program should return
18+
* the vertex where the path had to terminate, in this case your program should
19+
* return B.
20+
*
21+
* The graph will have at least 2 vertices and all the vertices in the graph
22+
* will be connected.
23+
*
24+
* https://www.coderbyte.com/information/Hamiltonian%20Path
25+
*
26+
* @param {array} strArr
27+
* @return {string}
28+
*/
29+
function hamiltonianPath(strArr) {
30+
// Parse input
31+
let [nodes, edges, path] = strArr.map(str =>
32+
str.substr(1, str.length - 2).split(',')
33+
);
34+
35+
const graph = new Graph();
36+
37+
// Add empty nodes
38+
nodes.forEach(key => {
39+
graph.addNode(key);
40+
});
41+
42+
// Add edges
43+
edges.forEach(edge => {
44+
const [nodeA, nodeB] = edge.split('-');
45+
graph.node(nodeA).addEdge(nodeB);
46+
graph.node(nodeB).addEdge(nodeA);
47+
});
48+
49+
// https://en.wikipedia.org/wiki/Hamiltonian_path
50+
51+
const missingConnections = graph.getMissingPathConnections(path);
52+
53+
if (missingConnections.length === 0) {
54+
return 'yes';
55+
}
56+
return missingConnections[0];
57+
}
58+
59+
class Graph {
60+
constructor() {
61+
this.nodes = new Map();
62+
}
63+
64+
addNode(key) {
65+
this.nodes.set(key, new Node(key));
66+
return this.node(key);
67+
}
68+
69+
node(key) {
70+
return this.nodes.get(key);
71+
}
72+
73+
getMissingPathConnections(nodeKeyArr) {
74+
const missingConnections = [];
75+
for (let i = 1; i < nodeKeyArr.length; i++) {
76+
const nodeA = this.node(nodeKeyArr[i - 1]);
77+
const keyB = nodeKeyArr[i];
78+
if (!nodeA.hasEdge(keyB)) {
79+
missingConnections.push(nodeA.key);
80+
}
81+
}
82+
return missingConnections;
83+
}
84+
}
85+
86+
class Node {
87+
constructor(key) {
88+
this.key = key;
89+
this.edges = new Map();
90+
}
91+
92+
addEdge(key, weight = 1) {
93+
this.edges.set(key, weight);
94+
}
95+
96+
hasEdge(key) {
97+
return this.edges.has(key);
98+
}
99+
}
100+
101+
module.exports = hamiltonianPath;

hard/hamiltonian_path.test.js

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
const hamiltonianPath = require('./hamiltonian_path');
2+
3+
describe('hamiltonianPath()', () => {
4+
test('passes Coderbyte.com tests', () => {
5+
expect(
6+
hamiltonianPath(['(A,B,C,D)', '(A-B,A-D,B-D,A-C)', '(C,A,D,B)'])
7+
).toBe('yes');
8+
9+
expect(
10+
hamiltonianPath(['(A,B,C,D)', '(A-B,A-D,B-D,A-C)', '(D,A,B,C)'])
11+
).toBe('B');
12+
13+
expect(hamiltonianPath(['(A,B,C)', '(B-A,C-B)', '(C,B,A)'])).toBe(
14+
'yes'
15+
);
16+
17+
expect(
18+
hamiltonianPath(['(X,Y,Z,Q)', '(X-Y,Y-Q,Y-Z)', '(Z,Y,Q,X)'])
19+
).toBe('Q');
20+
21+
expect(
22+
hamiltonianPath(['(X,Y,Z,Q)', '(X-Y,Y-Q,Y-Z,X-Q)', '(Z,Y,Q,X)'])
23+
).toBe('yes');
24+
25+
expect(
26+
hamiltonianPath(['(X,Y,Z,Q)', '(X-Y,Y-Q,Y-Z,X-Q)', '(Q,Y,Z,X)'])
27+
).toBe('Z');
28+
29+
expect(
30+
hamiltonianPath(['(X,Y,Z,Q)', '(X-Y,Y-Q,Y-Z,X-Q)', '(Q,X,Y,Z)'])
31+
).toBe('yes');
32+
33+
expect(
34+
hamiltonianPath([
35+
'(A,B,C,D,E,F)',
36+
'(A-B,A-D,B-D,B-C,C-F,E-D)',
37+
'(F,C,B,A,D,E)'
38+
])
39+
).toBe('yes');
40+
41+
expect(
42+
hamiltonianPath([
43+
'(A,B,C,D,E,F)',
44+
'(A-B,A-D,B-D,B-C,C-F,E-D)',
45+
'(E,F,C,B,D,A)'
46+
])
47+
).toBe('E');
48+
49+
expect(
50+
hamiltonianPath([
51+
'(A,B,C,D,E,F,G)',
52+
'(A-B,A-D,B-D,B-C,C-F,E-D,F-E,G-F)',
53+
'(G,F,E,D,B,C,A)'
54+
])
55+
).toBe('C');
56+
});
57+
});

0 commit comments

Comments
 (0)