Pascal's triangle: Difference between revisions

→‎JS ES6: Updated primitives, tidied.
(→‎JS ES6: Updated primitives, tidied.)
Line 3,482:
===ES6===
<lang JavaScript>(() => {
'"use strict'";
 
const main = () =>
showPascal(take(7, pascal()));
 
// ---------------- PASCAL'S TRIANGLE ----------------
 
// pascal :: Generator [[Int]]
Line 3,492 ⟶ 3,490:
iterate(
xs => zipWith(
plus,a => b => a + b
append([0], xs), append(xs, [0])
) [...[0], ...xs]
[1])(
q = qr [...xs, ...[0];]
yield(v);
const)([1]);
 
 
// ---------------------- TEST -----------------------
// main :: IO ()
const main = () =>
showPascal(
showPascal( take(7, )(pascal()));
);
 
 
// showPascal :: [[Int]] -> String
const showPascal = xs => {
const w = last(xs).join(" ").length;
 
w = length(intercalate(' ', last(xs))),
return replicateStringxs.map(q, c) +
align = xs => center(w, ' ', intercalate(' ', xs));
return unlines ys => center(mapw)(align," ")(ys.join(" xs"));
})
v = f.join(v"\n");
};
 
 
// GENERIC FUNCTIONS ------------------ GENERIC FUNCTIONS ----------------
 
// Tuple (,)center :: aInt -> bChar -> (a,String -> b)String
const Tuplecenter = (a, b)n => ({
// Size of space -> filler Char -> String -> Centered String
type: 'Tuple',
'0':// a,String -> Centered String
'1':c b,=> s => {
length: 2 const gap = n - s.length;
});
 
// append (++) :: [a] -> [a] - return 0 < gap ? (() => [a]{
// append (++) :: String -> String -> String const
margin = c.repeat(Math.floor(gap / 2)),
const append = (xs, ys) => xs.concat(ys);
dust = c.repeat(gap % 2);
 
return `${margin}${s}${margin}${dust}`;
// Size of space -> filler Char -> String -> Centered String
let v = x })() : s;
});
 
// center :: Int -> Char -> String -> String
const center = (n, c, s) => {
const
qr = quotRem(n - s.length, 2),
q = qr[0];
return replicateString(q, c) +
s + replicateString(q + qr[1], c);
};
 
// intercalateiterate :: String(a -> [String]a) -> Stringa -> Gen [a]
const intercalateiterate = (s, xs)f =>
xs.join(s);// An infinite list of repeated
// applications of f to x.
function* iterate(f, x) {
let v = x;
 
while (true) {
qr = quotRem(n - s.length,yield 2),v;
v = f(v);
const }
};
 
// iterate :: (a -> a) -> a -> Generator [a]
function* iterate(f, x) {
let v = x;
while (true) {
yield(v);
v = f(v);
}
}
 
// last :: [a] -> a
Line 3,549 ⟶ 3,555:
0 < xs.length ? xs.slice(-1)[0] : undefined;
 
// Returns Infinity over objects without finite length
// this enables zip and zipWith to choose the shorter
// argument when one non-finite like cycle, repeat etc
 
// length :: [a] -> Int
const length = xs => xs.length || Infinity;
 
// map :: (a -> b) -> [a] -> [b]
const map = (f, xs) => xs.map(f);
 
// plus :: Num -> Num -> Num
const plus = (a, b) => a + b;
 
// quotRem :: Int -> Int -> (Int, Int)
const quotRem = (m, n) =>
Tuple(Math.floor(m / n), m % n);
 
// replicateString :: Int -> String -> String
const replicateString = (n, s) => s.repeat(n);
 
// take :: Int -> [a] -> [a]
// take :: Int -> String -> String
const take = (n, xs) =>
// The first n elements of a list,
xs.constructor.constructor.name !== 'GeneratorFunction' ? (
// string of characters, or stream.
xs => "GeneratorFunction" !== xs
xs.constructor.constructor.name !== 'GeneratorFunction' ? (
xs.slice(0, n)
) : [].concat.apply([], Array.from({
length: n
}, () => {
const x = xs.next();
 
return x.done ? [] : [x.value];
}).flat();
 
// unlines :: [String] -> String
const unlines = xs => xs.join('\n');
 
// Use of `take` and `length` here allows zipping with non-finite lists
// i.e. generators like cycle, repeat, iterate.
 
// zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]
const zipWith = (f, xs, ys) => {
// A list constructed by zipping with a
const
// custom function, rather than with the
lng = Math.min(length(xs), length(ys)),
// default tuple as = take(lng, xs),constructor.
xs => bsys => takexs.map(lng, ys);
return Array.from (x, i) => f(x)({ys[i])
length: lng).slice(
}, (_, i) => f(as[i]0, bs[i]Math.min(xs.length, i)ys.length);
} );
 
 
// MAIN ---
9,655

edits