Pythagorean triples: Difference between revisions

Content added Content deleted
No edit summary
(→‎JS ES6: Updated primitives, tidied.)
Line 2,927: Line 2,927:
Exhaustive search of a full cartesian product. Not scalable.
Exhaustive search of a full cartesian product. Not scalable.
<lang JavaScript>(() => {
<lang JavaScript>(() => {
'use strict';
"use strict";


// Arguments: predicate, maximum perimeter
// Arguments: predicate, maximum perimeter
// pythTripleCount :: ((Int, Int, Int) -> Bool) -> Int -> Int
// pythTripleCount :: ((Int, Int, Int) -> Bool) -> Int -> Int
const pythTripleCount = (p, maxPerim) => {
const pythTripleCount = p =>
maxPerim => {
const xs = enumFromTo(1, Math.floor(maxPerim / 2));
const
xs = enumFromTo(1)(
Math.floor(maxPerim / 2)
);


return concatMap(x =>
return xs.flatMap(
concatMap(y =>
x => xs.slice(x).flatMap(
concatMap(z =>
y => xs.slice(y).flatMap(
((x + y + z <= maxPerim) &&
z => ((x + y + z <= maxPerim) &&
(x * x + y * y === z * z) &&
((x * x) + (y * y) === z * z) &&
p(x, y, z)) ? [
p(x, y, z)) ? [
[x, y, z]
[x, y, z]
] : [], // (Empty lists disappear under concatenation)
] : []
xs.slice(y)), xs.slice(x)), xs
)
)
)
.length;
).length;
};
};


// GENERIC FUNCTIONS --------------------------------------
// ---------------------- TEST -----------------------
const main = () => [10, 100, 1000]
.map(n => ({
maxPerimeter: n,
triples: pythTripleCount(() => true)(n),
primitives: pythTripleCount(
(x, y) => gcd(x)(y) === 1
)(n)
}));


// concatMap :: (a -> [b]) -> [a] -> [b]
const concatMap = (f, xs) =>
xs.length > 0 ? [].concat.apply([], xs.map(f)) : [];


// ---------------- GENERIC FUNCTIONS ----------------
// enumFromTo :: Enum a => a -> a -> [a]
const enumFromTo = (m, n) =>
(typeof m !== 'number' ? (
enumFromToChar
) : enumFromToInt)
.apply(null, [m, n]);


// enumFromToInt :: Int -> Int -> [Int]
// abs :: Num -> Num
const enumFromToInt = (m, n) =>
const abs =
n >= m ? Array.from({
// Absolute value of a given number
length: Math.floor(n - m) + 1
// without the sign.
}, (_, i) => m + i) : [];
x => 0 > x ? (
-x
) : x;


// gcd :: Int -> Int -> Int
const gcd = (x, y) => {
const _gcd = (a, b) => (b === 0 ? a : _gcd(b, a % b));
return _gcd(Math.abs(x), Math.abs(y));
};


// enumFromTo :: Int -> Int -> [Int]
// MAIN ---------------------------------------------------
return [10, 100, 1000]
const enumFromTo = m =>
.map(n => ({
n => Array.from({
maxPerimeter: n,
length: 1 + n - m
triples: pythTripleCount(x => true, n),
}, (_, i) => m + i);

primitives: pythTripleCount((x, y, _) => gcd(x, y) === 1, n)

}));
// gcd :: Integral a => a -> a -> a
const gcd = x =>
y => {
const zero = x.constructor(0);
const go = (a, b) =>
zero === b ? (
a
) : go(b, a % b);

return go(abs(x), abs(y));
};


// MAIN ---
return main();
})();</lang>
})();</lang>
{{Out}}
{{Out}}