Last active
January 2, 2020 21:41
-
-
Save tripolskypetr/08a93675c99c6ea83c2bec211e92b08c to your computer and use it in GitHub Desktop.
Functional style oriented graph traversal https://jsfiddle.net/tripolskypetr/132am0bL/
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// o <- end | |
// / \ n | |
// f g \ / | |
// \ / m n | |
// e \ / | |
// | p | | |
// h d \ / | |
// \ | l | |
// i c / | |
// \ | k | |
// b / | |
// \ / | |
// a <- start | |
// This is a directed graph. Accordingly, we represent it in the form of pairs of points | |
const roads = { | |
a: ['b', 'k'], | |
b: ['c'], | |
c: ['i', 'd'], | |
d: ['h', 'e'], | |
e: ['f', 'g', 'o'], | |
f: [], | |
g: [], | |
h: [], | |
i: [], | |
k: ['l'], | |
l: ['m', 'p'], | |
m: ['o', 'n'], | |
n: [], | |
o: [], | |
p: [], | |
}; | |
// We write a function that will iterate over all possible roads, adjusted for the fact that two different points can lead to the same endpoint (applyWay). We also write a function that recursively collects graph connections into segments (buildWays) the start and end points. | |
const buildWays = (dt) => [...roads[dt].map((d) => [dt, d]), ...roads[dt].map((d) => buildWays(d)).reduce((a, v) => a.concat(v), [])]; | |
const first = (arr) => arr[0]; | |
const last = (arr) => arr[arr.length - 1]; | |
const applyWay = (dot) => { | |
const apply = []; | |
ways.forEach((way) => { | |
if (last(way) === dot) { | |
roads[dot].forEach((road) => apply.push([...way, ...road])); | |
} else { | |
return; | |
} | |
}); | |
ways.push(...apply); | |
} | |
// Count all kinds of segments. Using the start and end points we connect the segments in various routes | |
const ways = buildWays('a'); // [ ['a','b'], ['b','c'] ] | |
Object.keys(roads).forEach((dot) => applyWay(dot)/* [ ['a','b', 'c', 'i'], ... ] */); | |
// From the start and end points we find the shortest route | |
const calculateRoute = (to, from = 'a') => ways | |
.filter((way) => first(way) === from && last(way) === to) | |
.sort((a, b) => a.length > b.length ? 1 : a.length < b.length ? -1 : 0); | |
console.log(first(calculateRoute('o'))); // [ 'a', 'k', 'l', 'm', 'o' ] |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment