Tree traversal: Difference between revisions
Content added Content deleted
(→JS ES6: Updated primitives, tidied) |
|||
Line 5,904: | Line 5,904: | ||
{{Trans|Python}} |
{{Trans|Python}} |
||
<lang JavaScript>(() => { |
<lang JavaScript>(() => { |
||
"use strict"; |
|||
// foldTree :: (a -> [b] -> b) -> Tree a -> b |
|||
⚫ | |||
// The catamorphism on trees. A summary |
|||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
// preorder :: a -> [[a]] -> [a] |
// preorder :: a -> [[a]] -> [a] |
||
const preorder = x => |
const preorder = x => |
||
xs => [x, ... |
xs => [x, ...xs.flat()]; |
||
// inorder :: a -> [[a]] -> [a] |
// inorder :: a -> [[a]] -> [a] |
||
const inorder = x => |
const inorder = x => |
||
xs => |
xs => Boolean(xs.length) ? ( |
||
[...xs[0], x, ... |
[...xs[0], x, ...xs.slice(1).flat()] |
||
) : [x]; |
) : [x]; |
||
// postorder :: a -> [[a]] -> [a] |
// postorder :: a -> [[a]] -> [a] |
||
const postorder = x => |
const postorder = x => |
||
xs => [... |
xs => [...xs.flat(), x]; |
||
// levelOrder :: Tree a -> [a] |
// levelOrder :: Tree a -> [a] |
||
const levelOrder = tree => |
const levelOrder = tree => |
||
levels(tree).flat(); |
|||
takeWhile(length)( |
|||
iterate(concatMap(nest))( |
|||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
// ------------------------TEST------------------------ |
// ------------------------TEST------------------------ |
||
⚫ | |||
const main = () => { |
const main = () => { |
||
const tree = Node(1)([ |
const tree = Node(1)([ |
||
Line 5,961: | Line 5,946: | ||
// task: 'Visualize a tree' |
// task: 'Visualize a tree' |
||
console.log([ |
console.log([ |
||
" ┌ 4 ─ 7", |
|||
" ┌ 2 ┤", |
|||
" │ └ 5", |
|||
" 1 ┤", |
|||
" │ ┌ 8", |
|||
" └ 3 ─ 6 ┤", |
|||
" └ 9" |
|||
].join( |
].join("\n")); |
||
[preorder, inorder, postorder] |
[preorder, inorder, postorder] |
||
.forEach( |
.forEach(f => console.log( |
||
justifyRight(11)(" ")(`${f.name}:`), |
|||
foldTree(f)( |
|||
tree |
|||
⚫ | |||
⚫ | |||
) |
) |
||
); |
)); |
||
console.log( |
console.log( |
||
`levelOrder: ${levelOrder(tree)}` |
|||
) |
); |
||
}; |
}; |
||
// ----------------- |
// ---------------------- TREES ---------------------- |
||
// Node :: a -> [Tree a] -> Tree a |
// Node :: a -> [Tree a] -> Tree a |
||
Line 5,993: | Line 5,976: | ||
// more child trees. |
// more child trees. |
||
xs => ({ |
xs => ({ |
||
type: |
type: "Node", |
||
root: v, |
root: v, |
||
nest: xs || [] |
nest: xs || [] |
||
}); |
}); |
||
// concat :: [[a]] -> [a] |
|||
// concat :: [String] -> String |
|||
const concat = xs => |
|||
⚫ | |||
xs.every(x => 'string' === typeof x) ? ( |
|||
'' |
|||
) : [] |
|||
).concat(...xs) : xs; |
|||
// |
// foldTree :: (a -> [b] -> b) -> Tree a -> b |
||
const |
const foldTree = f => { |
||
// The catamorphism on trees. A summary |
|||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
// iterate :: (a -> a) -> a -> Gen [a] |
|||
⚫ | |||
const iterate = f => |
|||
function*(x) { |
|||
let v = x; |
|||
// levels :: Tree a -> [[a]] |
|||
const levels = tree => { |
|||
// A list of lists, grouping the root |
|||
// values of each level of the tree. |
|||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
...node.nest.reduceRight(go, t) |
|||
⚫ | |||
}; |
}; |
||
⚫ | |||
⚫ | |||
// --------------------- GENERIC --------------------- |
|||
// justifyRight :: Int -> Char -> String -> String |
// justifyRight :: Int -> Char -> String -> String |
||
Line 6,025: | Line 6,021: | ||
// The string s, preceded by enough padding (with |
// The string s, preceded by enough padding (with |
||
// the character c) to reach the string length n. |
// the character c) to reach the string length n. |
||
c => s => |
c => s => Boolean(s) ? ( |
||
s.padStart(n, c) |
s.padStart(n, c) |
||
) : |
) : ""; |
||
// length :: [a] -> Int |
|||
const length = xs => |
|||
// Returns Infinity over objects without finite |
|||
// length. This enables zip and zipWith to choose |
|||
// the shorter argument when one is non-finite, |
|||
// like cycle, repeat etc |
|||
(Array.isArray(xs) || 'string' === typeof xs) ? ( |
|||
xs.length |
|||
) : Infinity; |
|||
// map :: (a -> b) -> [a] -> [b] |
|||
const map = f => |
|||
// The list obtained by applying f to each element of xs. |
|||
// (The image of xs under f). |
|||
xs => (Array.isArray(xs) ? ( |
|||
xs |
|||
) : xs.split('')).map(f); |
|||
// nest :: Tree a -> [a] |
|||
const nest = tree => tree.nest; |
|||
⚫ | |||
const root = tree => tree.root; |
|||
// takeWhile :: (a -> Bool) -> Gen [a] -> [a] |
|||
const takeWhile = p => xs => { |
|||
const ys = []; |
|||
let |
|||
nxt = xs.next(), |
|||
v = nxt.value; |
|||
while (!nxt.done && p(v)) { |
|||
ys.push(v); |
|||
nxt = xs.next(); |
|||
v = nxt.value |
|||
⚫ | |||
return ys; |
|||
⚫ | |||
// MAIN --- |
// MAIN --- |