100 lines
2.7 KiB
JavaScript
100 lines
2.7 KiB
JavaScript
|
|
(() => {
|
||
|
|
// TRAVERSALS -------------------------------------------------------------
|
||
|
|
|
||
|
|
// preorder Tree a -> [a]
|
||
|
|
const preorder = a => [a[v]]
|
||
|
|
.concat(a[l] ? preorder(a[l]) : [])
|
||
|
|
.concat(a[r] ? preorder(a[r]) : []);
|
||
|
|
|
||
|
|
// inorder Tree a -> [a]
|
||
|
|
const inorder = a =>
|
||
|
|
(a[l] ? inorder(a[l]) : [])
|
||
|
|
.concat(a[v])
|
||
|
|
.concat(a[r] ? inorder(a[r]) : []);
|
||
|
|
|
||
|
|
// postorder Tree a -> [a]
|
||
|
|
const postorder = a =>
|
||
|
|
(a[l] ? postorder(a[l]) : [])
|
||
|
|
.concat(a[r] ? postorder(a[r]) : [])
|
||
|
|
.concat(a[v]);
|
||
|
|
|
||
|
|
// levelorder Tree a -> [a]
|
||
|
|
const levelorder = a => (function go(x) {
|
||
|
|
return x.length ? (
|
||
|
|
x[0] ? (
|
||
|
|
[x[0][v]].concat(
|
||
|
|
go(x.slice(1)
|
||
|
|
.concat([x[0][l], x[0][r]])
|
||
|
|
)
|
||
|
|
)
|
||
|
|
) : go(x.slice(1))
|
||
|
|
) : [];
|
||
|
|
})([a]);
|
||
|
|
|
||
|
|
|
||
|
|
// GENERIC FUNCTIONS -----------------------------------------------------
|
||
|
|
|
||
|
|
// A list of functions applied to a list of arguments
|
||
|
|
// <*> :: [(a -> b)] -> [a] -> [b]
|
||
|
|
const ap = (fs, xs) => //
|
||
|
|
[].concat.apply([], fs.map(f => //
|
||
|
|
[].concat.apply([], xs.map(x => [f(x)]))));
|
||
|
|
|
||
|
|
// intercalate :: String -> [a] -> String
|
||
|
|
const intercalate = (s, xs) => xs.join(s);
|
||
|
|
|
||
|
|
// justifyLeft :: Int -> Char -> Text -> Text
|
||
|
|
const justifyLeft = (n, cFiller, strText) =>
|
||
|
|
n > strText.length ? (
|
||
|
|
(strText + cFiller.repeat(n))
|
||
|
|
.substr(0, n)
|
||
|
|
) : strText;
|
||
|
|
|
||
|
|
// unlines :: [String] -> String
|
||
|
|
const unlines = xs => xs.join('\n');
|
||
|
|
|
||
|
|
// unwords :: [String] -> String
|
||
|
|
const unwords = xs => xs.join(' ');
|
||
|
|
|
||
|
|
// zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]
|
||
|
|
const zipWith = (f, xs, ys) =>
|
||
|
|
Array.from({
|
||
|
|
length: Math.min(xs.length, ys.length)
|
||
|
|
}, (_, i) => f(xs[i], ys[i]));
|
||
|
|
|
||
|
|
// TEST -------------------------------------------------------------------
|
||
|
|
// asciiTree :: String
|
||
|
|
const asciiTree = unlines([
|
||
|
|
' 1',
|
||
|
|
' / \\',
|
||
|
|
' / \\',
|
||
|
|
' / \\',
|
||
|
|
' 2 3',
|
||
|
|
' / \\ /',
|
||
|
|
' 4 5 6',
|
||
|
|
' / / \\',
|
||
|
|
' 7 8 9'
|
||
|
|
]);
|
||
|
|
|
||
|
|
const [v, l, r] = [0, 1, 2],
|
||
|
|
tree = [1, [2, [4, [7]],
|
||
|
|
[5]
|
||
|
|
],
|
||
|
|
[3, [6, [8],
|
||
|
|
[9]
|
||
|
|
]]
|
||
|
|
],
|
||
|
|
|
||
|
|
// fs :: [(Tree a -> [a])]
|
||
|
|
fs = [preorder, inorder, postorder, levelorder];
|
||
|
|
|
||
|
|
return asciiTree + '\n\n' +
|
||
|
|
intercalate('\n',
|
||
|
|
zipWith(
|
||
|
|
(f, xs) => justifyLeft(12, ' ', f.name + ':') + unwords(xs),
|
||
|
|
fs,
|
||
|
|
ap(fs, [tree])
|
||
|
|
)
|
||
|
|
);
|
||
|
|
})();
|