From 3ffc76713f6db4c33f20588ce6896ea3c2bae2a7 Mon Sep 17 00:00:00 2001 From: Charles Date: Sat, 17 Aug 2019 21:39:43 +0200 Subject: wip directory for each language --- haskell/wip/021-amicable_numbers.hs | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 haskell/wip/021-amicable_numbers.hs (limited to 'haskell/wip/021-amicable_numbers.hs') diff --git a/haskell/wip/021-amicable_numbers.hs b/haskell/wip/021-amicable_numbers.hs new file mode 100644 index 0000000..867765d --- /dev/null +++ b/haskell/wip/021-amicable_numbers.hs @@ -0,0 +1,31 @@ +-- Amicable numbers +-- +-- Problem 21 +-- Let d(n) be defined as the sum of proper divisors of n +-- (numbers less than n which divide evenly into n). +-- If d(a) = b and d(b) = a, where a ≠ b, then a and b are an amicable +-- pair and each of a and b are called amicable numbers. +-- +-- For example, the proper divisors of 220 are 1, 2, 4, 5, 10, 11, 20, 22, 44, 55 and 110; +-- therefore d(220) = 284. The proper divisors of 284 are 1, 2, 4, 71 and 142; so d(284) = 220. +-- +-- Evaluate the sum of all the amicable numbers under 10000. + + +-- 5s isnt pretty, divSum is probably the root of evil +main = print (sum $ map fst (filterAmicable [2..10000])) + +filterAmicable :: [Int] -> [(Int, Int)] +filterAmicable xs = filter (\(n, s) -> n /= s && any ((==)(s, n)) sums) sums + where sums = [(x, divSum x) | x <- xs] + +divSum :: Int -> Int +divSum n = factorise 2 + where factorise d + | d > nSqrt = 1 + | rest == 0 && d /= quotient = d + quotient + factorise (d + 1) + | rest == 0 && d == quotient = quotient + factorise (d + 1) + | otherwise = factorise (d + 1) + where quotient = n `div` d + rest = n `mod` d + nSqrt = floor $ sqrt $ fromIntegral n -- cgit