RosettaCodeData/Task/Tree-traversal/JavaScript/tree-traversal-6.js

129 lines
3.0 KiB
JavaScript

(() => {
"use strict";
// preorder :: a -> [[a]] -> [a]
const preorder = x =>
xs => [x, ...xs.flat()];
// inorder :: a -> [[a]] -> [a]
const inorder = x =>
xs => Boolean(xs.length) ? (
[...xs[0], x, ...xs.slice(1).flat()]
) : [x];
// postorder :: a -> [[a]] -> [a]
const postorder = x =>
xs => [...xs.flat(), x];
// levelOrder :: Tree a -> [a]
const levelOrder = tree =>
levels(tree).flat();
// ------------------------TEST------------------------
// main :: IO ()
const main = () => {
const tree = Node(1)([
Node(2)([
Node(4)([
Node(7)([])
]),
Node(5)([])
]),
Node(3)([
Node(6)([
Node(8)([]),
Node(9)([])
])
])
]);
// Generated by code in Rosetta Code
// task: 'Visualize a tree'
console.log([
" + 4 - 7",
" + 2 ¦",
" ¦ + 5",
" 1 ¦",
" ¦ + 8",
" + 3 - 6 ¦",
" + 9"
].join("\n"));
[preorder, inorder, postorder]
.forEach(f => console.log(
justifyRight(11)(" ")(`${f.name}:`),
foldTree(f)(
tree
)
));
console.log(
`levelOrder: ${levelOrder(tree)}`
);
};
// ---------------------- TREES ----------------------
// Node :: a -> [Tree a] -> Tree a
const Node = v =>
// Constructor for a Tree node which connects a
// value of some kind to a list of zero or
// more child trees.
xs => ({
type: "Node",
root: v,
nest: xs || []
});
// foldTree :: (a -> [b] -> b) -> Tree a -> b
const foldTree = f => {
// The catamorphism on trees. A summary
// value obtained by a depth-first fold.
const go = tree => f(
tree.root
)(
tree.nest.map(go)
);
return go;
};
// levels :: Tree a -> [[a]]
const levels = tree => {
// A list of lists, grouping the root
// values of each level of the tree.
const go = (a, node) => {
const [h, ...t] = 0 < a.length ? a : [
[]
];
return [
[node.root, ...h],
...node.nest.reduceRight(go, t)
];
};
return go([], tree);
};
// --------------------- GENERIC ---------------------
// justifyRight :: Int -> Char -> String -> String
const justifyRight = n =>
// The string s, preceded by enough padding (with
// the character c) to reach the string length n.
c => s => Boolean(s) ? (
s.padStart(n, c)
) : "";
// MAIN ---
return main();
})();