Family Day update
This commit is contained in:
parent
aac6731f2c
commit
9ad63ea473
2442 changed files with 39761 additions and 8255 deletions
|
|
@ -1,99 +1,167 @@
|
|||
(() => {
|
||||
// TRAVERSALS -------------------------------------------------------------
|
||||
'use strict';
|
||||
|
||||
// preorder Tree a -> [a]
|
||||
const preorder = a => [a[v]]
|
||||
.concat(a[l] ? preorder(a[l]) : [])
|
||||
.concat(a[r] ? preorder(a[r]) : []);
|
||||
// foldTree :: (a -> [b] -> b) -> Tree a -> b
|
||||
const foldTree = f =>
|
||||
// The catamorphism on trees. A summary
|
||||
// value obtained by a depth-first fold.
|
||||
tree => {
|
||||
const go = x => f(x.root)(
|
||||
x.nest.map(go)
|
||||
);
|
||||
return go(tree);
|
||||
};
|
||||
|
||||
// inorder Tree a -> [a]
|
||||
const inorder = a =>
|
||||
(a[l] ? inorder(a[l]) : [])
|
||||
.concat(a[v])
|
||||
.concat(a[r] ? inorder(a[r]) : []);
|
||||
// preorder :: a -> [[a]] -> [a]
|
||||
const preorder = x =>
|
||||
xs => [x, ...concat(xs)];
|
||||
|
||||
// postorder Tree a -> [a]
|
||||
const postorder = a =>
|
||||
(a[l] ? postorder(a[l]) : [])
|
||||
.concat(a[r] ? postorder(a[r]) : [])
|
||||
.concat(a[v]);
|
||||
// inorder :: a -> [[a]] -> [a]
|
||||
const inorder = x =>
|
||||
xs => length(xs) ? (
|
||||
[...xs[0], x, ...concat(xs.slice(1))]
|
||||
) : [x];
|
||||
|
||||
// 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]])
|
||||
)
|
||||
// postorder :: a -> [[a]] -> [a]
|
||||
const postorder = x =>
|
||||
xs => [...concat(xs), x];
|
||||
|
||||
// levelOrder :: Tree a -> [a]
|
||||
const levelOrder = tree =>
|
||||
concatMap(map(root))(
|
||||
takeWhile(length)(
|
||||
iterate(concatMap(nest))(
|
||||
[tree]
|
||||
)
|
||||
) : 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])
|
||||
)
|
||||
);
|
||||
|
||||
// ------------------------TEST------------------------
|
||||
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)
|
||||
)
|
||||
};
|
||||
|
||||
// -----------------GENERIC FUNCTIONS------------------
|
||||
|
||||
// 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 || []
|
||||
});
|
||||
|
||||
// concat :: [[a]] -> [a]
|
||||
// concat :: [String] -> String
|
||||
const concat = xs =>
|
||||
0 < xs.length ? (
|
||||
xs.every(x => 'string' === typeof x) ? (
|
||||
''
|
||||
) : []
|
||||
).concat(...xs) : xs;
|
||||
|
||||
// concatMap :: (a -> [b]) -> [a] -> [b]
|
||||
const concatMap = f =>
|
||||
xs => xs.flatMap(f);
|
||||
|
||||
// iterate :: (a -> a) -> a -> Gen [a]
|
||||
const iterate = f =>
|
||||
function*(x) {
|
||||
let v = x;
|
||||
while (true) {
|
||||
yield(v);
|
||||
v = f(v);
|
||||
}
|
||||
};
|
||||
|
||||
// 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 => n > s.length ? (
|
||||
s.padStart(n, c)
|
||||
) : s;
|
||||
|
||||
// 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;
|
||||
|
||||
// root :: Tree a -> a
|
||||
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 ---
|
||||
return main();
|
||||
})();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue