129 lines
3.0 KiB
JavaScript
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();
|
|
})();
|