2022-01-21 01:00:18 +05:30
|
|
|
---
|
|
|
|
id: 5949b579404977fbaefcd737
|
2022-01-22 20:38:20 +05:30
|
|
|
title: 友愛数
|
2022-01-21 01:00:18 +05:30
|
|
|
challengeType: 5
|
|
|
|
forumTopicId: 302225
|
|
|
|
dashedName: amicable-pairs
|
|
|
|
---
|
|
|
|
|
|
|
|
# --description--
|
|
|
|
|
2022-01-22 20:38:20 +05:30
|
|
|
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")です。
|
2022-01-21 01:00:18 +05:30
|
|
|
|
2022-01-22 20:38:20 +05:30
|
|
|
**例:**
|
2022-01-21 01:00:18 +05:30
|
|
|
|
2022-01-22 20:38:20 +05:30
|
|
|
**1184** と **1210** は、真の約数の和から友愛数だと分かります。
|
2022-01-21 01:00:18 +05:30
|
|
|
|
|
|
|
<ul>
|
2022-01-22 20:38:20 +05:30
|
|
|
<li>1、2、4、8、16、32、37、74、148、296、592</li>
|
|
|
|
<li>1、2、5、10、11、22、55、110、121、242、605</li>
|
2022-01-21 01:00:18 +05:30
|
|
|
</ul>
|
|
|
|
|
|
|
|
# --instructions--
|
|
|
|
|
2022-01-22 20:38:20 +05:30
|
|
|
計算して、20,000 以下の 友愛数を表示します (8 つあります)。
|
2022-01-21 01:00:18 +05:30
|
|
|
|
|
|
|
# --hints--
|
|
|
|
|
2022-01-22 20:38:20 +05:30
|
|
|
`amicablePairsUpTo` という関数です。
|
2022-01-21 01:00:18 +05:30
|
|
|
|
|
|
|
```js
|
|
|
|
assert(typeof amicablePairsUpTo === 'function');
|
|
|
|
```
|
|
|
|
|
2022-01-22 20:38:20 +05:30
|
|
|
`amicablePairsUpTo(300)` は `[[220,284]]` を返します。
|
2022-01-21 01:00:18 +05:30
|
|
|
|
|
|
|
```js
|
|
|
|
assert.deepEqual(amicablePairsUpTo(300), answer300);
|
|
|
|
```
|
|
|
|
|
2022-01-22 20:38:20 +05:30
|
|
|
`amicablePairsUpTo(3000)` は `[[220,284],[1184,1210],[2620,2924]]` を返します。
|
2022-01-21 01:00:18 +05:30
|
|
|
|
|
|
|
```js
|
|
|
|
assert.deepEqual(amicablePairsUpTo(3000), answer3000);
|
|
|
|
```
|
|
|
|
|
2022-01-22 20:38:20 +05:30
|
|
|
`amicablePairsUpTo(20000)` は `[[220,284],[1184,1210],[2620,2924],[5020,5564],[6232,6368],[10744,10856],[12285,14595],[17296,18416]]` を返します。
|
2022-01-21 01:00:18 +05:30
|
|
|
|
|
|
|
```js
|
|
|
|
assert.deepEqual(amicablePairsUpTo(20000), answer20000);
|
|
|
|
```
|
|
|
|
|
|
|
|
# --seed--
|
|
|
|
|
|
|
|
## --after-user-code--
|
|
|
|
|
|
|
|
```js
|
|
|
|
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--
|
|
|
|
|
|
|
|
```js
|
|
|
|
function amicablePairsUpTo(maxNum) {
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
# --solutions--
|
|
|
|
|
|
|
|
```js
|
|
|
|
// 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));
|
|
|
|
}
|
|
|
|
```
|