Skip to content

Instantly share code, notes, and snippets.

@eckdanny
Created June 24, 2014 13:53
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save eckdanny/7b2be5f885b7e4f1a887 to your computer and use it in GitHub Desktop.
Save eckdanny/7b2be5f885b7e4f1a887 to your computer and use it in GitHub Desktop.
Dijkstra's Shortest Path for Weighted Directed Graphs
// http://coderbyte.com/CodingArea/GuestEditor.php?ct=Weighted%20Path&lan=JavaScript
var input = ['4','A','B','C','D', 'A|B|2', 'C|B|11', 'C|D|3', 'B|D|2'];
var output = 'A-B-D';
console.log(output === (function (strArr) { 'use strict';
// Process input data
var count = strArr.shift()
, nodes = strArr.splice(0, count)
, edges = strArr.map(function (str) {
var arr = str.split('|');
arr[2] = arr[2] * 1;
return arr;
});
//
// Helper Fns
//
// Returns adjacent edges
var getNeighbors = function (node) {
return edges.reduce(function (neighbors, edge) {
var isCounted = function (node) {
return neighbors.indexOf(node) > -1;
};
if (node === edge[0] && !isCounted(edge[1])) {
neighbors.push(edge[1]);
} else if (node === edge[1] && !isCounted(edge[0])) {
neighbors.push(edge[0]);
}
return neighbors;
}, []);
};
// Returns weight for a path between two nodes
var getEdgeWeight = function (a, b) {
for (var i = 0, N = edges.length; i < N; i++) {
if ([a, b].indexOf(edges[i][0]) > -1 && [a, b].indexOf(edges[i][1]) > -1) {
return edges[i][2];
}
}
throw "edge does not exist!";
};
// Returns the forward path created from backtrace
var trace = function (nodes, path) {
var prev = function (node) {
return paths[node].prev;
}
var prevNode, stack = [nodes[count - 1]];
while (prevNode = prev(stack[0])) {
stack.unshift(prevNode);
};
return stack;
};
// Sets the initial step weights and traversals
var init = function (nodes) {
var paths = {};
for (var i in nodes) {
paths[nodes[i]] = {
prev: null,
steps: i == 0 ? 0 : Infinity
};
}
return paths;
};
// Generate the output string
var outStr = function (nodes, trace) {
if (nodes[0] !== trace[0] || nodes[nodes.length - 1] !== trace[trace.length - 1]) {
return -1;
} else {
return trace.join('-');
}
};
//
// Solve
//
var paths = init(nodes)
, curNode
, fringe = [nodes[0]]
;
while (curNode = fringe.shift()) {
getNeighbors(curNode).forEach(function (node) {
if (paths[curNode].steps + getEdgeWeight(node, curNode) < paths[node].steps) {
paths[node].steps = paths[curNode].steps + getEdgeWeight(node, curNode);
paths[node].prev = curNode;
fringe.push(node);
}
});
}
return outStr(nodes, trace(nodes, paths));
})(input));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment