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,78 +1,121 @@
// Floyd triangles of 5 and 14 rows
// right-aligned monospaced columns (nMargin allows for extra spacing)
// () --> s
function main() {
// minimum space between numbers - adjust for visual preference
var nMargin = 1;
(function () {
'use strict';
// Formatted strings for Floyd's triangles of 5 and 14 rows
return (function (lstN) {
return lstN.map(function (nFloydRows) {
var lstRows = floydIntegerLists(nFloydRows),
iLast = nFloydRows - 1;
// FLOYD's TRIANGLE -------------------------------------------------------
return colsSpacedRight(
lstRows,
// Minimum space required per number cell
// nMargin more than the width of the final number
lstRows[iLast][iLast].toString().length + nMargin
)
}).join('\n\n');
})([5, 14]);
}
// floyd :: Int -> [[Int]]
function floyd(n) {
return snd(mapAccumL(function (start, row) {
return [start + row + 1, enumFromTo(start, start + row)];
}, 1, enumFromTo(0, n - 1)));
};
// n Floyd's triangle rows
// n --> [[n]]
function floydIntegerLists(nRows) {
// showFloyd :: [[Int]] -> String
function showFloyd(xss) {
var ws = map(compose([succ, length, show]), last(xss));
return unlines(map(function (xs) {
return concat(zipWith(function (w, x) {
return justifyRight(w, ' ', show(x));
}, ws, xs));
}, xss));
};
// Full integer list folded into list of rows
// [n] --> [[n]]
return (function triangleNumbers(lstInt, startWidth) {
var n = startWidth || 1;
return n > lstInt.length ? [] : [lstInt.slice(0, n)].concat(
triangleNumbers(lstInt.slice(n), n + 1)
)
})(
range(
1,
Math.floor(
(nRows * nRows) / 2
) + Math.ceil(
nRows / 2
)
)
);
}
// GENERIC FUNCTIONS ------------------------------------------------------
// list of list of numbers --> lines of fixed right-aligned col width
// [[n]] --> s
function colsSpacedRight(lstLines, nColWidth) {
return lstLines.reduce(
function (s, line) {
return s + line.map(function (n) {
return rightAligned(n, nColWidth)
}).join('') + '\n';
}, ''
)
}
// compose :: [(a -> a)] -> (a -> a)
function compose(fs) {
return function (x) {
return fs.reduceRight(function (a, f) {
return f(a);
}, x);
};
};
// range(1, 20) --> [1..20]
function range(m, n) {
return Array.apply(null, Array(n - m + 1)).map(
function (x, i) {
// concat :: [[a]] -> [a] | [String] -> String
function concat(xs) {
if (xs.length > 0) {
var unit = typeof xs[0] === 'string' ? '' : [];
return unit.concat.apply(unit, xs);
} else return [];
};
// enumFromTo :: Int -> Int -> [Int]
function enumFromTo(m, n) {
return Array.from({
length: Math.floor(n - m) + 1
}, function (_, i) {
return m + i;
}
);
}
});
};
// Integer as right-padded string of given width
// n --> n --> s
function rightAligned(n, width) {
var strN = n.toString();
return Array(width - strN.length + 1).join(' ') + strN;
}
// justifyRight :: Int -> Char -> Text -> Text
function justifyRight(n, cFiller, strText) {
return n > strText.length ? (cFiller.repeat(n) + strText)
.slice(-n) : strText;
};
console.log( // if the context is a browser
main()
);
// last :: [a] -> a
function last(xs) {
return xs.length ? xs.slice(-1)[0] : undefined;
};
// length :: [a] -> Int
function length(xs) {
return xs.length;
};
// map :: (a -> b) -> [a] -> [b]
function map(f, xs) {
return xs.map(f);
};
// 'The mapAccumL function behaves like a combination of map and foldl;
// it applies a function to each element of a list, passing an accumulating
// parameter from left to right, and returning a final value of this
// accumulator together with the new list.' (See hoogle )
// mapAccumL :: (acc -> x -> (acc, y)) -> acc -> [x] -> (acc, [y])
function mapAccumL(f, acc, xs) {
return xs.reduce(function (a, x) {
var pair = f(a[0], x);
return [pair[0], a[1].concat([pair[1]])];
}, [acc, []]);
};
// show ::
// (a -> String) f, Num n =>
// a -> maybe f -> maybe n -> String
var show = JSON.stringify;
// snd :: (a, b) -> b
function snd(tpl) {
return Array.isArray(tpl) ? tpl[1] : undefined;
};
// succ :: Int -> Int
function succ(x) {
return x + 1;
};
// unlines :: [String] -> String
function unlines(xs) {
return xs.join('\n');
};
// zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]
function zipWith(f, xs, ys) {
var ny = ys.length;
return (xs.length <= ny ? xs : xs.slice(0, ny))
.map(function (x, i) {
return f(x, ys[i]);
});
};
// TEST ( n=5 and n=14 rows ) ---------------------------------------------
return unlines(map(function (n) {
return showFloyd(floyd(n)) + '\n';
}, [5, 14]));
})();

View file

@ -1,36 +1,97 @@
#!/usr/bin/env js
(() => {
'use strict';
function main() {
print('Floyd 5:');
floyd(5);
print('\nFloyd 14:');
floyd(14);
}
// FLOYD's TRIANGLE -------------------------------------------------------
// floyd :: Int -> [[Int]]
const floyd = n => snd(mapAccumL(
(start, row) => [start + row + 1, enumFromTo(start, start + row)],
1, enumFromTo(0, n - 1)
));
// showFloyd :: [[Int]] -> String
const showFloyd = xss => {
const ws = map(compose([succ, length, show]), last(xss));
return unlines(
map(xs => concat(zipWith(
(w, x) => justifyRight(w, ' ', show(x)), ws, xs
)),
xss
)
);
};
// GENERIC FUNCTIONS ------------------------------------------------------
// compose :: [(a -> a)] -> (a -> a)
const compose = fs => x => fs.reduceRight((a, f) => f(a), x);
// 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 [];
};
// enumFromTo :: Int -> Int -> [Int]
const enumFromTo = (m, n) =>
Array.from({
length: Math.floor(n - m) + 1
}, (_, i) => m + i);
// justifyRight :: Int -> Char -> Text -> Text
const justifyRight = (n, cFiller, strText) =>
n > strText.length ? (
(cFiller.repeat(n) + strText)
.slice(-n)
) : strText;
// last :: [a] -> a
const last = xs => xs.length ? xs.slice(-1)[0] : undefined;
// length :: [a] -> Int
const length = xs => xs.length;
// map :: (a -> b) -> [a] -> [b]
const map = (f, xs) => xs.map(f)
// 'The mapAccumL function behaves like a combination of map and foldl;
// it applies a function to each element of a list, passing an accumulating
// parameter from left to right, and returning a final value of this
// accumulator together with the new list.' (See hoogle )
// mapAccumL :: (acc -> x -> (acc, y)) -> acc -> [x] -> (acc, [y])
const mapAccumL = (f, acc, xs) =>
xs.reduce((a, x) => {
const pair = f(a[0], x);
return [pair[0], a[1].concat([pair[1]])];
}, [acc, []]);
// show ::
// (a -> String) f, Num n =>
// a -> maybe f -> maybe n -> String
const show = JSON.stringify;
// snd :: (a, b) -> b
const snd = tpl => Array.isArray(tpl) ? tpl[1] : undefined;
// succ :: Int -> Int
const succ = x => x + 1
// unlines :: [String] -> String
const unlines = xs => xs.join('\n');
function padLeft(s, w) {
for (s = String(s); s.length < w; s = ' ' + s);
return s;
}
// zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]
const zipWith = (f, xs, ys) => {
const ny = ys.length;
return (xs.length <= ny ? xs : xs.slice(0, ny))
.map((x, i) => f(x, ys[i]));
};
// TEST ( n=5 and n=14 rows ) ---------------------------------------------
function floyd(nRows) {
var lowerLeft = nRows * (nRows - 1) / 2 + 1;
var lowerRight = nRows * (nRows + 1) / 2;
var colWidths = [];
for (var col = lowerLeft; col <= lowerRight; col++) {
colWidths.push(String(col).length);
}
var num = 1;
for (var row = 0; row < nRows; row++) {
var line = [];
for (var col = 0; col <= row; col++, num++) {
line.push(padLeft(num, colWidths[col]));
}
print(line.join(' '));
}
}
main();
return unlines(map(n => showFloyd(floyd(n)) + '\n', [5, 14]))
})();

View file

@ -0,0 +1,36 @@
#!/usr/bin/env js
function main() {
print('Floyd 5:');
floyd(5);
print('\nFloyd 14:');
floyd(14);
}
function padLeft(s, w) {
for (s = String(s); s.length < w; s = ' ' + s);
return s;
}
function floyd(nRows) {
var lowerLeft = nRows * (nRows - 1) / 2 + 1;
var lowerRight = nRows * (nRows + 1) / 2;
var colWidths = [];
for (var col = lowerLeft; col <= lowerRight; col++) {
colWidths.push(String(col).length);
}
var num = 1;
for (var row = 0; row < nRows; row++) {
var line = [];
for (var col = 0; col <= row; col++, num++) {
line.push(padLeft(num, colWidths[col]));
}
print(line.join(' '));
}
}
main();