(() => { 'use strict'; // LINES OF SIERPINSKI TRIANGLE AT LEVEL N ------------------------------- // sierpinski :: Int -> [String] const sierpTriangle = n => // Previous triangle centered with left and right padding, (n > 0) ? concat(ap([ map(xs => intercalate(xs, ap( [s => concat(replicate(Math.pow(2, (n - 1)), s))], [' ', '-'] ))), // above a pair of duplicates, placed one character apart. map(xs => intercalate('+', [xs, xs])) ], [sierpTriangle(n - 1)])) : ['▲']; // GENERIC FUNCTIONS ----------------------------------------------------- // replicate :: Int -> a -> [a] const replicate = (n, a) => { let v = [a], o = []; if (n < 1) return o; while (n > 1) { if (n & 1) o = o.concat(v); n >>= 1; v = v.concat(v); } return o.concat(v); }; // curry :: ((a, b) -> c) -> a -> b -> c const curry = f => a => b => f(a, b); // map :: (a -> b) -> [a] -> [b] const map = curry((f, xs) => xs.map(f)); // Apply a list of functions 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)])))); // unlines :: [String] -> String const unlines = xs => xs.join('\n'); // intercalate :: String -> [a] -> String const intercalate = (s, xs) => xs.join(s); // concat :: [[a]] -> [a] || [String] -> String const concat = xs => { if (xs.length > 0) { const unit = typeof xs[0] === 'string' ? '' : []; return unit.concat.apply(unit, xs); } else return []; }; // TEST ------------------------------------------------------------------ return unlines(sierpTriangle(4)); })();