RosettaCodeData/Task/Pascals-triangle/JavaScript/pascals-triangle-4.js
2017-09-25 22:28:19 +02:00

68 lines
1.9 KiB
JavaScript

(() => {
'use strict';
// PASCAL'S TRIANGLE ------------------------------------------------------
// pascal :: Int -> [[Int]]
const pascal = n =>
foldl(a => {
const xs = a.slice(-1)[0]; // Previous row
return append(a, [
zipWith(
(a, b) => a + b,
append([0], xs),
append(xs, [0])
)
]);
}, [
[1] // Initial seed row
], enumFromTo(1, n - 1));
// GENERIC FUNCTIONS ------------------------------------------------------
// (++) :: [a] -> [a] -> [a]
const append = (xs, ys) => xs.concat(ys);
// enumFromTo :: Int -> Int -> [Int]
const enumFromTo = (m, n) =>
Array.from({
length: Math.floor(n - m) + 1
}, (_, i) => m + i);
// flip :: (a -> b -> c) -> b -> a -> c
const flip = f => (a, b) => f(b, a);
// foldl :: (b -> a -> b) -> b -> [a] -> b
const foldl = (f, a, xs) => xs.reduce(f, a);
// foldr (a -> b -> b) -> b -> [a] -> b
const foldr = (f, a, xs) => xs.reduceRight(flip(f), a);
// map :: (a -> b) -> [a] -> [b]
const map = (f, xs) => xs.map(f);
// min :: Ord a => a -> a -> a
const min = (a, b) => b < a ? b : a;
// zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]
const zipWith = (f, xs, ys) =>
Array.from({
length: min(xs.length, ys.length)
}, (_, i) => f(xs[i], ys[i]));
// TEST -------------------------------------------------------------------
return foldr((x, a) => {
const strIndent = a.indent;
return {
rows: strIndent + map(n => (' ' + n)
.slice(-4), x)
.join('') + '\n' + a.rows,
indent: strIndent + ' '
};
}, {
rows: '',
indent: ''
}, pascal(7))
.rows;
})();