83 lines
2.6 KiB
JavaScript
83 lines
2.6 KiB
JavaScript
(function (n) {
|
|
|
|
var chain = function (xs, f) { // Monadic bind/chain
|
|
return [].concat.apply([], xs.map(f));
|
|
},
|
|
|
|
hArea = function (x, y, z) {
|
|
var s = (x + y + z) / 2,
|
|
a = s * (s - x) * (s - y) * (s - z);
|
|
return a ? Math.sqrt(a) : 0;
|
|
},
|
|
|
|
gcd = function (m, n) { return n ? gcd(n, m % n) : m; },
|
|
|
|
rng = function (m, n) {
|
|
return Array.apply(null, Array(n - m + 1)).map(function (x, i) {
|
|
return m + i;
|
|
});
|
|
},
|
|
|
|
sum = function (a, x) { return a + x; };
|
|
|
|
// DEFINING THE SORTED SUB-SET IN TERMS OF A LIST MONAD
|
|
|
|
var lstHeron = chain( rng(1, n), function (x) {
|
|
return chain( rng(x, n), function (y) {
|
|
return chain( rng(y, n), function (z) {
|
|
|
|
return (
|
|
(x + y > z) &&
|
|
gcd(gcd(x, y), z) === 1 && // Primitive.
|
|
(function () { // Heronian.
|
|
var a = hArea(x, y, z);
|
|
return a && (a === parseInt(a, 10))
|
|
})()
|
|
) ? [[x, y, z]] : []; // Monadic inject or fail
|
|
|
|
})})}).sort(function (a, b) {
|
|
var dArea = hArea.apply(null, a) - hArea.apply(null, b);
|
|
if (dArea) return dArea;
|
|
else {
|
|
var dPerim = a.reduce(sum, 0) - b.reduce(sum, 0);
|
|
return dPerim ? dPerim : (a[2] - b[2]);
|
|
}
|
|
});
|
|
|
|
// OUPUT FORMATTED AS TWO WIKITABLES
|
|
|
|
var lstColumns = ['Sides Perimeter Area'.split(' ')],
|
|
fnData = function (lst) {
|
|
return [JSON.stringify(lst), lst.reduce(sum, 0), hArea.apply(null, lst)];
|
|
},
|
|
wikiTable = function (lstRows, blnHeaderRow, strStyle) {
|
|
return '{| class="wikitable" ' + (
|
|
strStyle ? 'style="' + strStyle + '"' : ''
|
|
) + lstRows.map(function (lstRow, iRow) {
|
|
var strDelim = ((blnHeaderRow && !iRow) ? '!' : '|');
|
|
|
|
return '\n|-\n' + strDelim + ' ' + lstRow.map(function (v) {
|
|
return typeof v === 'undefined' ? ' ' : v;
|
|
}).join(' ' + strDelim + strDelim + ' ');
|
|
}).join('') + '\n|}';
|
|
};
|
|
|
|
return 'Found: ' + lstHeron.length +
|
|
' primitive Heronian triangles with sides up to ' + n + '.\n\n' +
|
|
'(Showing first 10, sorted by increasing area, ' +
|
|
'perimeter, and longest side)\n\n' +
|
|
wikiTable(
|
|
lstColumns.concat(lstHeron.slice(0, 10).map(fnData)),
|
|
true
|
|
) + '\n\n' +
|
|
'All primitive Heronian triangles in this range where area = 210\n' +
|
|
'\n(also in order of increasing perimeter and longest side)\n\n' +
|
|
wikiTable(
|
|
lstColumns.concat(lstHeron.filter(function (x) {
|
|
return 210 === hArea.apply(null, x);
|
|
}).map(fnData)),
|
|
true
|
|
) + '\n\n';
|
|
|
|
})(200);
|