Skip to content

Instantly share code, notes, and snippets.

@earlonrails
Last active November 26, 2023 09:34
Show Gist options
  • Save earlonrails/f25ebd224ede7bc6338a839ec9469a53 to your computer and use it in GitHub Desktop.
Save earlonrails/f25ebd224ede7bc6338a839ec9469a53 to your computer and use it in GitHub Desktop.
shortest path and bfs in es6 javascript
#!/usr/bin/env node
// Question found here:
// https://stackoverflow.com/questions/32527026/shortest-path-in-javascript
// Based on the first accepted answer
"use strict"
const expect = require('expect.js')
class Graph {
constructor(props) {
this.neighbors = {}
}
addEdge(u, v) {
if (!this.neighbors[u]) this.neighbors[u] = []
this.neighbors[u].push(v)
}
bfs(start) {
if (!this.neighbors[start] || !this.neighbors[start].length) {
return [start]
}
var results = {"nodes": []},
queue = this.neighbors[start],
count = 1
while(queue.length) {
var node = queue.shift()
if (!results[node] || !results[node].visited) {
results[node] = {visited: true, steps: count}
results["nodes"].push(node)
if (this.neighbors[node]) {
if (this.neighbors[node].length) {
count++
queue.push(...this.neighbors[node])
} else {
continue
}
}
}
}
return results
}
shortestPath(start, end) {
if (start == end) {
return [start, end]
}
var queue = [start],
visited = {},
predecessor = {},
tail = 0,
path
while(tail < queue.length) {
var u = queue[tail++]
if (!this.neighbors[u]) {
continue
}
var neighbors = this.neighbors[u]
for(var i = 0; i < neighbors.length; ++i) {
var v = neighbors[i]
if (visited[v]) {
continue
}
visited[v] = true
if (v === end) { // Check if the path is complete.
path = [ v ] // If so, backtrack through the path.
while (u !== start) {
path.push(u)
u = predecessor[u]
}
path.push(u)
path.reverse()
return path
}
predecessor[v] = u
queue.push(v)
}
}
return path
}
}
// start -> [A]→[B]→[C]→[D] [E]
// ↓ ↑ ↓
// [F]→[G]→[H] [I]→[J]
// ↓ ↓ ↓
// [K]→[L]→[M] [N] [O] -> end
// ↓ ↓ ↑
// [P]→[Q]→[R]→[S]→[T]
// Shortest Path 6 A→B→C→D→I→J→O
var createGraph = function() {
var g = new Graph()
g.addEdge('A', 'B')
g.addEdge('B', 'C')
g.addEdge('C', 'D')
g.addEdge('D', 'I')
g.addEdge('A', 'F')
g.addEdge('G', 'B')
g.addEdge('G', 'H')
g.addEdge('H', 'M')
g.addEdge('I', 'N')
g.addEdge('I', 'J')
g.addEdge('J', 'O')
g.addEdge('K', 'L')
g.addEdge('K', 'P')
g.addEdge('L', 'M')
g.addEdge('M', 'R')
g.addEdge('P', 'Q')
g.addEdge('Q', 'R')
g.addEdge('R', 'S')
g.addEdge('S', 'T')
g.addEdge('T', 'O')
return g
}
var bfsGraph = createGraph()
var bfsPath = bfsGraph.bfs('A')
expect(bfsPath).to.eql({ nodes: [ 'B', 'F', 'C', 'D', 'I', 'N', 'J', 'O' ],
B: { visited: true, steps: 1 },
F: { visited: true, steps: 2 },
C: { visited: true, steps: 2 },
D: { visited: true, steps: 3 },
I: { visited: true, steps: 4 },
N: { visited: true, steps: 5 },
J: { visited: true, steps: 5 },
O: { visited: true, steps: 6 } })
console.dir(bfsPath)
var shortestPathGraph = createGraph()
var path = shortestPathGraph.shortestPath('A', 'O')
expect(path).to.eql([ 'A', 'B', 'C', 'D', 'I', 'J', 'O'])
console.log(path.join('→'))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment