Initial data commit
This commit is contained in:
parent
72d218235f
commit
f23f22d71c
199087 changed files with 3378941 additions and 0 deletions
211
Task/Abundant-odd-numbers/JavaScript/abundant-odd-numbers.js
Normal file
211
Task/Abundant-odd-numbers/JavaScript/abundant-odd-numbers.js
Normal file
|
|
@ -0,0 +1,211 @@
|
|||
(() => {
|
||||
'use strict';
|
||||
const main = () => {
|
||||
|
||||
// abundantTuple :: Int -> [(Int, Int)]
|
||||
const abundantTuple = n => {
|
||||
// Either a list containing the tuple of N
|
||||
// and its divisor sum (if n is abundant),
|
||||
// or otherwise an empty list.
|
||||
const x = divisorSum(n);
|
||||
return n < x ? ([
|
||||
Tuple(n)(x)
|
||||
]) : [];
|
||||
};
|
||||
|
||||
// divisorSum :: Int -> Int
|
||||
const divisorSum = n => {
|
||||
// Sum of the divisors of n.
|
||||
const
|
||||
floatRoot = Math.sqrt(n),
|
||||
intRoot = Math.floor(floatRoot),
|
||||
lows = filter(x => 0 === n % x)(
|
||||
enumFromTo(1)(intRoot)
|
||||
);
|
||||
return sum(lows.concat(map(quot(n))(
|
||||
intRoot === floatRoot ? (
|
||||
lows.slice(1, -1)
|
||||
) : lows.slice(1)
|
||||
)));
|
||||
};
|
||||
|
||||
// TEST ---------------------------------------
|
||||
console.log(
|
||||
'First 25 abundant odd numbers, with their divisor sums:'
|
||||
)
|
||||
console.log(unlines(map(showTuple)(
|
||||
take(25)(
|
||||
concatMapGen(abundantTuple)(
|
||||
enumFromThen(1)(3)
|
||||
)
|
||||
)
|
||||
)));
|
||||
console.log(
|
||||
'\n\n1000th abundant odd number, with its divisor sum:'
|
||||
)
|
||||
console.log(showTuple(
|
||||
take(1)(drop(999)(
|
||||
concatMapGen(abundantTuple)(
|
||||
enumFromThen(1)(3)
|
||||
)
|
||||
))[0]
|
||||
))
|
||||
console.log(
|
||||
'\n\nFirst abundant odd number above 10^9, with divisor sum:'
|
||||
)
|
||||
const billion = Math.pow(10, 9);
|
||||
console.log(showTuple(
|
||||
take(1)(
|
||||
concatMapGen(abundantTuple)(
|
||||
enumFromThen(1 + billion)(3 + billion)
|
||||
)
|
||||
)[0]
|
||||
))
|
||||
};
|
||||
|
||||
|
||||
// GENERAL REUSABLE FUNCTIONS -------------------------
|
||||
|
||||
// Tuple (,) :: a -> b -> (a, b)
|
||||
const Tuple = a => b => ({
|
||||
type: 'Tuple',
|
||||
'0': a,
|
||||
'1': b,
|
||||
length: 2
|
||||
});
|
||||
|
||||
// concatMapGen :: (a -> [b]) -> Gen [a] -> Gen [b]
|
||||
const concatMapGen = f =>
|
||||
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();
|
||||
}
|
||||
};
|
||||
|
||||
// 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);
|
||||
|
||||
// dropAround :: (a -> Bool) -> [a] -> [a]
|
||||
// dropAround :: (Char -> Bool) -> String -> String
|
||||
const dropAround = p => xs => dropWhile(p)(
|
||||
dropWhileEnd(p)(xs)
|
||||
);
|
||||
|
||||
// dropWhile :: (a -> Bool) -> [a] -> [a]
|
||||
// dropWhile :: (Char -> Bool) -> String -> String
|
||||
const dropWhile = p => xs => {
|
||||
const lng = xs.length;
|
||||
return 0 < lng ? xs.slice(
|
||||
until(i => i === lng || !p(xs[i]))(
|
||||
i => 1 + i
|
||||
)(0)
|
||||
) : [];
|
||||
};
|
||||
|
||||
// dropWhileEnd :: (a -> Bool) -> [a] -> [a]
|
||||
// dropWhileEnd :: (Char -> Bool) -> String -> String
|
||||
const dropWhileEnd = p => xs => {
|
||||
let i = xs.length;
|
||||
while (i-- && p(xs[i])) {}
|
||||
return xs.slice(0, i + 1);
|
||||
};
|
||||
|
||||
// enumFromThen :: Int -> Int -> Gen [Int]
|
||||
const enumFromThen = x =>
|
||||
// A non-finite stream of integers,
|
||||
// starting with x and y, and continuing
|
||||
// with the same interval.
|
||||
function*(y) {
|
||||
const d = y - x;
|
||||
let v = y + d;
|
||||
yield x;
|
||||
yield y;
|
||||
while (true) {
|
||||
yield v;
|
||||
v = d + v;
|
||||
}
|
||||
};
|
||||
|
||||
// enumFromTo :: Int -> Int -> [Int]
|
||||
const enumFromTo = m => n =>
|
||||
Array.from({
|
||||
length: 1 + n - m
|
||||
}, (_, i) => m + i);
|
||||
|
||||
// filter :: (a -> Bool) -> [a] -> [a]
|
||||
const filter = f => xs => xs.filter(f);
|
||||
|
||||
// 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
|
||||
|
||||
// length :: [a] -> Int
|
||||
const length = xs =>
|
||||
(Array.isArray(xs) || 'string' === typeof xs) ? (
|
||||
xs.length
|
||||
) : Infinity;
|
||||
|
||||
// map :: (a -> b) -> [a] -> [b]
|
||||
const map = f => xs =>
|
||||
(Array.isArray(xs) ? (
|
||||
xs
|
||||
) : xs.split('')).map(f);
|
||||
|
||||
// quot :: Int -> Int -> Int
|
||||
const quot = n => m => Math.floor(n / m);
|
||||
|
||||
// show :: a -> String
|
||||
const show = JSON.stringify;
|
||||
|
||||
// showTuple :: Tuple -> String
|
||||
const showTuple = tpl =>
|
||||
'(' + enumFromTo(0)(tpl.length - 1)
|
||||
.map(x => unQuoted(show(tpl[x])))
|
||||
.join(',') + ')';
|
||||
|
||||
// sum :: [Num] -> Num
|
||||
const sum = xs => xs.reduce((a, x) => a + x, 0);
|
||||
|
||||
// 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');
|
||||
|
||||
// until :: (a -> Bool) -> (a -> a) -> a -> a
|
||||
const until = p => f => x => {
|
||||
let v = x;
|
||||
while (!p(v)) v = f(v);
|
||||
return v;
|
||||
};
|
||||
|
||||
// unQuoted :: String -> String
|
||||
const unQuoted = s =>
|
||||
dropAround(x => 34 === x.codePointAt(0))(
|
||||
s
|
||||
);
|
||||
|
||||
// MAIN ---
|
||||
return main();
|
||||
})();
|
||||
Loading…
Add table
Add a link
Reference in a new issue