2.7 KiB
2.7 KiB
id, title, challengeType, forumTopicId, dashedName
id | title | challengeType | forumTopicId | dashedName |
---|---|---|---|---|
5949b579404977fbaefcd737 | 友愛数 | 5 | 302225 | amicable-pairs |
--description--
2つの整数、$N$と$M$は、 $N \neq M$であり、[真の約数](https://rosettacode.org/wiki/Proper divisors "Proper divisors") の合計に関して、N
(\\mathrm{sum}(\\mathrm{propDivs}(N))
) = M
かつ $\mathrm{sum}(\mathrm{propDivs}(M)) = N$である場合に、[友愛数](https://en.wikipedia.org/wiki/Amicable numbers "wp: Amicable numbers")です。
例:
1184 と 1210 は、真の約数の和から友愛数だと分かります。
- 1、2、4、8、16、32、37、74、148、296、592
- 1、2、5、10、11、22、55、110、121、242、605
--instructions--
計算して、20,000 以下の 友愛数を表示します (8 つあります)。
--hints--
amicablePairsUpTo
という関数です。
assert(typeof amicablePairsUpTo === 'function');
amicablePairsUpTo(300)
は [[220,284]]
を返します。
assert.deepEqual(amicablePairsUpTo(300), answer300);
amicablePairsUpTo(3000)
は [[220,284],[1184,1210],[2620,2924]]
を返します。
assert.deepEqual(amicablePairsUpTo(3000), answer3000);
amicablePairsUpTo(20000)
は [[220,284],[1184,1210],[2620,2924],[5020,5564],[6232,6368],[10744,10856],[12285,14595],[17296,18416]]
を返します。
assert.deepEqual(amicablePairsUpTo(20000), answer20000);
--seed--
--after-user-code--
const answer300 = [[220, 284]];
const answer3000 = [
[220, 284],
[1184, 1210],
[2620, 2924]
];
const answer20000 = [
[220, 284],
[1184, 1210],
[2620, 2924],
[5020, 5564],
[6232, 6368],
[10744, 10856],
[12285, 14595],
[17296, 18416]
];
--seed-contents--
function amicablePairsUpTo(maxNum) {
return true;
}
--solutions--
// amicablePairsUpTo :: Int -> [(Int, Int)]
function amicablePairsUpTo(maxNum) {
return range(1, maxNum)
.map(x => properDivisors(x)
.reduce((a, b) => a + b, 0))
.reduce((a, m, i, lst) => {
const n = i + 1;
return (m > n) && lst[m - 1] === n ?
a.concat([
[n, m]
]) : a;
}, []);
}
// properDivisors :: Int -> [Int]
function properDivisors(n) {
if (n < 2) return [];
const rRoot = Math.sqrt(n);
const intRoot = Math.floor(rRoot);
const blnPerfectSquare = rRoot === intRoot;
const lows = range(1, intRoot)
.filter(x => (n % x) === 0);
return lows.concat(lows.slice(1)
.map(x => n / x)
.reverse()
.slice(blnPerfectSquare | 0));
}
// Int -> Int -> Maybe Int -> [Int]
function range(m, n, step) {
const d = (step || 1) * (n >= m ? 1 : -1);
return Array.from({
length: Math.floor((n - m) / d) + 1
}, (_, i) => m + (i * d));
}