September 2017 Update

This commit is contained in:
Ingy döt Net 2017-09-23 10:01:46 +02:00
parent bba7bfd280
commit ba8067c3b7
14570 changed files with 153136 additions and 63871 deletions

View file

@ -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));
})();

View 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);