module Euler.Util.Amicable
( amicableNumbers
) where
import Euler.Prelude hiding (max)
import qualified Data.List as List
import qualified Data.Map as Map
import Euler.Util.Prime (factorizations, properDivisorsOfPrimeProduct)
amicableNumbers :: Integer -> [Integer]
amicableNumbers max = List.filter isAmicable [2..max]
where
divisorSums = (List.sum . properDivisorsOfPrimeProduct) <$> factorizations max
d = (divisorSums Map.!)
d' = (`Map.lookup` divisorSums)
isAmicable a = let b = d a in b /= a && d' b == Just a