RosettaCodeData/Task/Harshad-or-Niven-series/JavaScript/harshad-or-niven-series-2.js
2017-09-25 22:28:19 +02:00

69 lines
1.9 KiB
JavaScript

(() => {
'use strict';
// HARSHADS ---------------------------------------------------------------
// nHarshads :: Int -> [Int]
const nHarshads = n => {
// isHarshad :: Int -> Bool
const isHarshad = n => 0 === n % sum(digitList(n));
return until(
dct => dct.nth === n,
dct => {
const
next = succ(dct.i),
blnHarshad = isHarshad(next);
return {
i: next,
hs: blnHarshad ? dct.hs.concat(next) : dct.hs,
nth: dct.nth + (blnHarshad ? 1 : 0)
};
}, {
i: 0,
hs: [],
nth: 0
}
)
.hs;
};
// GENERIC FUNCTIONS ------------------------------------------------------
// digitList :: Int -> [Int]
const digitList = n =>
n > 0 ? [n % 10].concat(digitList(Math.floor(n / 10))) : [];
// dropWhile :: (a -> Bool) -> [a] -> [a]
const dropWhile = (p, xs) => {
let i = 0;
for (let lng = xs.length;
(i < lng) && p(xs[i]); i++) {}
return xs.slice(i);
};
// head :: [a] -> a
const head = xs => xs.length ? xs[0] : undefined;
// a -> String
const show = x => JSON.stringify(x, null, 2);
// succ :: Int -> Int
const succ = x => x + 1
// sum :: (Num a) => [a] -> a
const sum = xs => xs.reduce((a, x) => a + x, 0);
// until :: (a -> Bool) -> (a -> a) -> a -> a
const until = (p, f, x) => {
const go = x => p(x) ? x : go(f(x));
return go(x);
};
// TEST -------------------------------------------------------------------
return show({
firstTwenty: nHarshads(20),
firstOver1000: head(dropWhile(x => x <= 1000, nHarshads(1000)))
});
})();