112 lines
2.8 KiB
JavaScript
112 lines
2.8 KiB
JavaScript
(() => {
|
|
'use strict';
|
|
|
|
// main :: IO ()
|
|
const main = () => {
|
|
const genMianChowla = mianChowlas();
|
|
console.log([
|
|
'Mian-Chowla terms 1-30:',
|
|
take(30)(
|
|
genMianChowla
|
|
),
|
|
|
|
'\nMian-Chowla terms 91-100:',
|
|
(
|
|
drop(60)(genMianChowla),
|
|
take(10)(
|
|
genMianChowla
|
|
)
|
|
)
|
|
].join('\n') + '\n');
|
|
};
|
|
|
|
// mianChowlas :: Gen [Int]
|
|
function* mianChowlas() {
|
|
let
|
|
mcs = [1],
|
|
sumSet = new Set([2]),
|
|
x = 1;
|
|
while (true) {
|
|
yield x;
|
|
[sumSet, mcs, x] = nextMC(sumSet, mcs, x);
|
|
}
|
|
}
|
|
|
|
// nextMC :: Set Int -> [Int] -> Int -> (Set Int, [Int], Int)
|
|
const nextMC = (setSums, mcs, n) => {
|
|
// Set of sums -> Series up to n -> Next term in series
|
|
const valid = x => {
|
|
for (const m of mcs) {
|
|
if (setSums.has(x + m)) return false;
|
|
}
|
|
return true;
|
|
};
|
|
const x = until(valid)(x => 1 + x)(n);
|
|
return [
|
|
sumList(mcs)(x)
|
|
.reduce(
|
|
(a, n) => (a.add(n), a),
|
|
setSums
|
|
),
|
|
mcs.concat(x),
|
|
x
|
|
];
|
|
};
|
|
|
|
// sumList :: [Int] -> Int -> [Int]
|
|
const sumList = xs =>
|
|
// Series so far -> additional term -> new sums
|
|
n => [2 * n].concat(xs.map(x => n + x));
|
|
|
|
|
|
// ---------------- GENERIC FUNCTIONS ----------------
|
|
|
|
// drop :: Int -> [a] -> [a]
|
|
// drop :: Int -> Generator [a] -> Generator [a]
|
|
// drop :: Int -> String -> String
|
|
const drop = n =>
|
|
xs => Infinity > length(xs) ? (
|
|
xs.slice(n)
|
|
) : (take(n)(xs), xs);
|
|
|
|
|
|
// length :: [a] -> Int
|
|
const length = xs =>
|
|
// Returns Infinity over objects without finite
|
|
// length. This enables zip and zipWith to choose
|
|
// the shorter argument when one is non-finite,
|
|
// like cycle, repeat etc
|
|
'GeneratorFunction' !== xs.constructor
|
|
.constructor.name ? (
|
|
xs.length
|
|
) : Infinity;
|
|
|
|
|
|
// take :: Int -> [a] -> [a]
|
|
// take :: Int -> String -> String
|
|
const take = n =>
|
|
// The first n elements of a list,
|
|
// string of characters, or stream.
|
|
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];
|
|
}));
|
|
|
|
|
|
// until :: (a -> Bool) -> (a -> a) -> a -> a
|
|
const until = p =>
|
|
f => x => {
|
|
let v = x;
|
|
while (!p(v)) v = f(v);
|
|
return v;
|
|
};
|
|
|
|
// MAIN ---
|
|
return main();
|
|
})();
|