112 lines
3.0 KiB
JavaScript
112 lines
3.0 KiB
JavaScript
(() => {
|
|
'use strict';
|
|
|
|
// babbageNumbers :: Int -> [Int]
|
|
const babbageNumbers = n =>
|
|
// Take the first n Babbage numbers,
|
|
take(n)(
|
|
// from the concatenation of outputs of
|
|
// a function which constructs the next number
|
|
// ending in 269696, and returns it wrapped
|
|
// in a list if it is a perfect square,
|
|
// or just returns an empty list if it
|
|
// is not a perfect square.
|
|
// The concatenation of the map output eliminates
|
|
// all empty lists, leaving a sequence of perfect
|
|
// squares which end in 269696.
|
|
concatMap(x => {
|
|
const
|
|
fx = 269696 + (1000000 * x),
|
|
root = Math.sqrt(fx);
|
|
return root === Math.floor(root) ? (
|
|
[Tuple(root)(fx)]
|
|
) : [];
|
|
// Mapped over non-finite integer series
|
|
// starting with 1.
|
|
})(enumFrom(1))
|
|
);
|
|
|
|
|
|
// TEST -----------------------------------------------
|
|
const main = () =>
|
|
// List of the first 10 positive integers
|
|
// whose squares end in 269696.
|
|
unlines(
|
|
map(pair => fst(pair) + '^2 -> ' + snd(pair))(
|
|
babbageNumbers(10)
|
|
));
|
|
|
|
|
|
// GENERIC FUNCTIONS ----------------------------------
|
|
|
|
// Tuple (,) :: a -> b -> (a, b)
|
|
const Tuple = a => b => ({
|
|
type: 'Tuple',
|
|
'0': a,
|
|
'1': b,
|
|
length: 2
|
|
});
|
|
|
|
// concatMap :: (a -> [b]) -> Gen [a] -> Gen [b]
|
|
const concatMap = f =>
|
|
// Instance of concatMap for non-finite streams.
|
|
function*(xs) {
|
|
let
|
|
x = xs.next(),
|
|
v = undefined;
|
|
while (!x.done) {
|
|
v = f(x.value);
|
|
if (0 < v.length) {
|
|
yield v[0];
|
|
}
|
|
x = xs.next();
|
|
}
|
|
};
|
|
|
|
// enumFrom :: Enum a => a -> [a]
|
|
function* enumFrom(x) {
|
|
let v = x;
|
|
while (true) {
|
|
yield v;
|
|
v = succ(v);
|
|
}
|
|
}
|
|
|
|
// fst :: (a, b) -> a
|
|
const fst = tpl => tpl[0];
|
|
|
|
// map :: (a -> b) -> [a] -> [b]
|
|
const map = f => xs =>
|
|
(Array.isArray(xs) ? (
|
|
xs
|
|
) : xs.split('')).map(f);
|
|
|
|
// root :: Tree a -> a
|
|
const root = tree => tree.root;
|
|
|
|
// snd :: (a, b) -> b
|
|
const snd = tpl => tpl[1];
|
|
|
|
// succ :: Enum a => a -> a
|
|
const succ = x =>
|
|
1 + x;
|
|
|
|
// take :: Int -> [a] -> [a]
|
|
// take :: Int -> String -> String
|
|
const take = n => xs =>
|
|
'GeneratorFunction' !== xs.constructor.constructor.name ? (
|
|
xs.slice(0, n)
|
|
) : [].concat.apply([], Array.from({
|
|
length: n
|
|
}, () => {
|
|
const x = xs.next();
|
|
return x.done ? [] : [x.value];
|
|
}));
|
|
|
|
// unlines :: [String] -> String
|
|
const unlines = xs => xs.join('\n');
|
|
|
|
// MAIN ---
|
|
return main();
|
|
})();
|