freeCodeCamp/curriculum/challenges/english/08-coding-interview-prep/rosetta-code/amicable-pairs.english.md

3.7 KiB

title id challengeType
Amicable pairs 5949b579404977fbaefcd737 5

Description

Two integers $N$ and $M$ are said to be amicable pairs if $N \neq M$ and the sum of the proper divisors of $N$ ($\mathrm{sum}(\mathrm{propDivs}(N))$) $= M$ as well as $\mathrm{sum}(\mathrm{propDivs}(M)) = N$. Example: 1184 and 1210 are an amicable pair, with proper divisors: 1, 2, 4, 8, 16, 32, 37, 74, 148, 296, 592 and 1, 2, 5, 10, 11, 22, 55, 110, 121, 242, 605 respectively. Task: Calculate and show here the Amicable pairs below 20,000 (there are eight). Related tasks Proper divisors Abundant, deficient and perfect number classifications Aliquot sequence classifications and its amicable classification.

Instructions

Tests

tests:
  - text: <code>amicablePairsUpTo</code> is a function.
    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>.");'

Challenge Seed

function amicablePairsUpTo (maxNum) {
  // Good luck!
  return true;
}

After Test

console.info('after the test');

Solution

// 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));
}