2018-09-30 22:01:58 +00:00
---
title: Amicable pairs
id: 5949b579404977fbaefcd737
challengeType: 5
---
## Description
< section id = 'description' >
2019-05-22 14:30:29 +00:00
Two integers $N$ and $M$ are said to be < a href = 'https://en.wikipedia.org/wiki/Amicable numbers' title = 'wp: Amicable numbers' target = '_blank' > amicable pairs</ a > if $N \neq M$ and the sum of the < a href = "https://rosettacode.org/wiki/Proper divisors" title = "Proper divisors" > proper divisors</ a > of $N$ ($\mathrm{sum}(\mathrm{propDivs}(N))$) $= M$ as well as $\mathrm{sum}(\mathrm{propDivs}(M)) = N$.
2019-02-24 10:04:29 +00:00
< b > Example:< / b >
< b > 1184< / b > and < b > 1210< / b > are an amicable pair, with proper divisors:
< ul >
2019-03-01 08:10:50 +00:00
< li > 1, 2, 4, 8, 16, 32, 37, 74, 148, 296, 592 and< / li >
< li > 1, 2, 5, 10, 11, 22, 55, 110, 121, 242, 605 respectively.< / li >
2019-02-24 10:04:29 +00:00
< / ul >
2018-09-30 22:01:58 +00:00
< / section >
## Instructions
< section id = 'instructions' >
2019-03-01 08:10:50 +00:00
Calculate and show here the Amicable pairs below 20,000 (there are eight).
2018-09-30 22:01:58 +00:00
< / section >
## Tests
< section id = 'tests' >
```yml
2018-10-04 13:37:37 +00:00
tests:
- text: < code > amicablePairsUpTo</ code > is a function.
2018-10-20 18:02:47 +00:00
testString: assert(typeof amicablePairsUpTo === 'function', '< code > amicablePairsUpTo< / code > is a function.');
- text: < code > amicablePairsUpTo(300)</ code > should return < code > [[220,284]]</ code > .
testString: assert.deepEqual(amicablePairsUpTo(300), answer300, '< code > amicablePairsUpTo(300)< / code > should return < code > [[220,284]]< / code > .');
- text: < code > amicablePairsUpTo(3000)</ code > should return < code > [[220,284],[1184,1210],[2620,2924]]</ code > .
testString: assert.deepEqual(amicablePairsUpTo(3000), answer3000, '< code > amicablePairsUpTo(3000)< / code > should return < code > [[220,284],[1184,1210],[2620,2924]]< / code > .');
- text: < code > amicablePairsUpTo(20000)</ code > should return < code > [[220,284],[1184,1210],[2620,2924],[5020,5564],[6232,6368],[10744,10856],[12285,14595],[17296,18416]]</ code > .
testString: assert.deepEqual(amicablePairsUpTo(20000), answer20000, '< code > amicablePairsUpTo(20000)< / code > should return < code > [[220,284],[1184,1210],[2620,2924],[5020,5564],[6232,6368],[10744,10856],[12285,14595],[17296,18416]]< / code > .');
2018-09-30 22:01:58 +00:00
```
< / section >
## Challenge Seed
< section id = 'challengeSeed' >
< div id = 'js-seed' >
```js
2019-02-26 08:07:07 +00:00
function amicablePairsUpTo(maxNum) {
2018-09-30 22:01:58 +00:00
// Good luck!
return true;
}
```
< / div >
### After Test
< div id = 'js-teardown' >
```js
2018-10-20 18:02:47 +00:00
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]
];
2018-09-30 22:01:58 +00:00
```
< / div >
< / section >
## Solution
< section id = 'solution' >
```js
// amicablePairsUpTo :: Int -> [(Int, Int)]
2019-02-26 08:07:07 +00:00
function amicablePairsUpTo(maxNum) {
2018-09-30 22:01:58 +00:00
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]
2019-02-26 08:07:07 +00:00
function properDivisors(n) {
2018-09-30 22:01:58 +00:00
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]
2019-02-26 08:07:07 +00:00
function range(m, n, step) {
2018-09-30 22:01:58 +00:00
const d = (step || 1) * (n >= m ? 1 : -1);
return Array.from({
length: Math.floor((n - m) / d) + 1
}, (_, i) => m + (i * d));
}
```
< / section >