September 2017 Update
This commit is contained in:
parent
bba7bfd280
commit
ba8067c3b7
14570 changed files with 153136 additions and 63871 deletions
|
|
@ -1,67 +1,62 @@
|
|||
// A Sierpinski triangle of order N,
|
||||
// constructed as 2^N lines of Pascal's triangle mod 2
|
||||
// and mapped to centred {1:asterisk, 0:space} strings
|
||||
(() => {
|
||||
'use strict';
|
||||
|
||||
(order => {
|
||||
// LINES OF SIERPINSKI TRIANGLE AT LEVEL N -------------------------------
|
||||
|
||||
// sierpinski :: Int -> [Bool]
|
||||
let sierpinski = intOrder => {
|
||||
// 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))], [' ', '-']
|
||||
))),
|
||||
|
||||
// asciiPascalMod2 :: Int -> [[Int]]
|
||||
let asciiPascalMod2 = nRows =>
|
||||
range(1, nRows - 1)
|
||||
.reduce(sofar => {
|
||||
let lstPrev = sofar.slice(-1)[0];
|
||||
// above a pair of duplicates, placed one character apart.
|
||||
map(xs => intercalate('+', [xs, xs]))
|
||||
], [sierpTriangle(n - 1)])) : ['▲'];
|
||||
|
||||
// The composition of (asciiBinary . mod 2 . add)
|
||||
// is reduced here to a rule from two parent characters
|
||||
// to a single child character.
|
||||
|
||||
// Rule 90 also reduces to the same XOR
|
||||
// relationship between left and right neighbours.
|
||||
// GENERIC FUNCTIONS -----------------------------------------------------
|
||||
|
||||
return sofar
|
||||
.concat([zipWith(
|
||||
(left, right) => left === right ? ' ' : '*',
|
||||
[' '].concat(lstPrev),
|
||||
lstPrev.concat(' ')
|
||||
)]);
|
||||
}, [
|
||||
['*'] // Tip of triangle
|
||||
]);
|
||||
|
||||
// Reduce/folding from the last item (base of list)
|
||||
// which has zero left indent.
|
||||
|
||||
// Each preceding row has one more indent space than the row beneath it
|
||||
return asciiPascalMod2(Math.pow(2, intOrder))
|
||||
.reduceRight((a, x) => {
|
||||
return {
|
||||
triangle: a.indent + x.join(' ') + '\n' + a.triangle,
|
||||
indent: a.indent + ' '
|
||||
}
|
||||
}, {
|
||||
triangle: '',
|
||||
indent: ''
|
||||
}).triangle
|
||||
// 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);
|
||||
};
|
||||
|
||||
// zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]
|
||||
let zipWith = (f, xs, ys) =>
|
||||
xs.length === ys.length ? (
|
||||
xs.map((x, i) => f(x, ys[i]))
|
||||
) : undefined,
|
||||
// curry :: ((a, b) -> c) -> a -> b -> c
|
||||
const curry = f => a => b => f(a, b);
|
||||
|
||||
// range(intFrom, intTo, optional intStep)
|
||||
// Int -> Int -> Maybe Int -> [Int]
|
||||
range = (m, n, step) => {
|
||||
let d = (step || 1) * (n >= m ? 1 : -1);
|
||||
// map :: (a -> b) -> [a] -> [b]
|
||||
const map = curry((f, xs) => xs.map(f));
|
||||
|
||||
return Array.from({
|
||||
length: Math.floor((n - m) / d) + 1
|
||||
}, (_, i) => m + (i * d));
|
||||
};
|
||||
// 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)]))));
|
||||
|
||||
return sierpinski(order);
|
||||
// unlines :: [String] -> String
|
||||
const unlines = xs => xs.join('\n');
|
||||
|
||||
})(4);
|
||||
// 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));
|
||||
})();
|
||||
|
|
|
|||
62
Task/Sierpinski-triangle/JavaScript/sierpinski-triangle-4.js
Normal file
62
Task/Sierpinski-triangle/JavaScript/sierpinski-triangle-4.js
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
(order => {
|
||||
// sierpinski :: Int -> [Bool]
|
||||
let sierpinski = intOrder => {
|
||||
|
||||
// asciiPascalMod2 :: Int -> [[Int]]
|
||||
let asciiPascalMod2 = nRows =>
|
||||
range(1, nRows - 1)
|
||||
.reduce(sofar => {
|
||||
let lstPrev = sofar.slice(-1)[0];
|
||||
|
||||
// The composition of (asciiBinary . mod 2 . add)
|
||||
// is reduced here to a rule from two parent characters
|
||||
// to a single child character.
|
||||
|
||||
// Rule 90 also reduces to the same XOR
|
||||
// relationship between left and right neighbours.
|
||||
|
||||
return sofar
|
||||
.concat([zipWith(
|
||||
(left, right) => left === right ? ' ' : '*',
|
||||
[' '].concat(lstPrev),
|
||||
lstPrev.concat(' ')
|
||||
)]);
|
||||
}, [
|
||||
['*'] // Tip of triangle
|
||||
]);
|
||||
|
||||
// Reduce/folding from the last item (base of list)
|
||||
// which has zero left indent.
|
||||
|
||||
// Each preceding row has one more indent space than the row beneath it
|
||||
return asciiPascalMod2(Math.pow(2, intOrder))
|
||||
.reduceRight((a, x) => {
|
||||
return {
|
||||
triangle: a.indent + x.join(' ') + '\n' + a.triangle,
|
||||
indent: a.indent + ' '
|
||||
}
|
||||
}, {
|
||||
triangle: '',
|
||||
indent: ''
|
||||
}).triangle
|
||||
};
|
||||
|
||||
// zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]
|
||||
let zipWith = (f, xs, ys) =>
|
||||
xs.length === ys.length ? (
|
||||
xs.map((x, i) => f(x, ys[i]))
|
||||
) : undefined,
|
||||
|
||||
// range(intFrom, intTo, optional intStep)
|
||||
// Int -> Int -> Maybe Int -> [Int]
|
||||
range = (m, n, step) => {
|
||||
let d = (step || 1) * (n >= m ? 1 : -1);
|
||||
|
||||
return Array.from({
|
||||
length: Math.floor((n - m) / d) + 1
|
||||
}, (_, i) => m + (i * d));
|
||||
};
|
||||
|
||||
return sierpinski(order);
|
||||
|
||||
})(4);
|
||||
Loading…
Add table
Add a link
Reference in a new issue