-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy path021_amicable_numbers.hs
84 lines (65 loc) · 2.89 KB
/
021_amicable_numbers.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
-- 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.
-- lists all prime factors of n
primefactors :: (Integral a) => a -> [a]
primefactors n = primefactorsAux n 2 []
primefactorsAux :: (Integral a) => a -> a -> [a] -> [a]
primefactorsAux n divisor factors
| n == 1 = factors
| (mod n divisor) == 0 = primefactorsAux (div n divisor) (divisor) (divisor:factors)
| otherwise = primefactorsAux n (divisor+1) factors
-- returns a list of all subsets of a given list represented as lists
subsets :: (Integral a) => [a] -> [[a]]
subsets list
| length list == 1 = [list]
| otherwise = nextSubsets ++ ( concatAll nextSubsets (head list) ) ++ [[head list]]
where nextSubsets = subsets (tail list)
-- takes a list of list and concatinates an given n to each list
concatAll :: (Integral a) => [[a]] -> a -> [[a]]
concatAll list n = [ n : x | x <- list]
-- lists all proper Divisors of n
listProperDivisors :: (Integral a) => a -> [a]
listProperDivisors 1 = [1]
listProperDivisors n = 1 : (filter (\x -> x /= n) $ delDuplicates $ map product (subsets $ primefactors n))
-- deletes all multiple instances in a list
delDuplicates :: (Integral a) => [a] -> [a]
delDuplicates l = delDuplicatesAux l []
delDuplicatesAux :: (Integral a) => [a] -> [a] -> [a]
delDuplicatesAux l retL
| l == [] = retL
| elem headL retL = delDuplicatesAux tailL retL
| otherwise = delDuplicatesAux tailL (headL : retL)
where tailL = tail l
headL = head l
-- returns sum of proper divisors of n
d :: (Integral a) => a -> a
d 1 = 1
d n = sum $ listProperDivisors n
-- lists all amicable numbers from 1 to n
listAmicableNumbers :: (Integral a) => a -> [(a,a)]
listAmicableNumbers n = [(x,y) | x <- [1..n], y <- [x+1..n], isAmicableNumber x y ]
where isAmicableNumber a b = d a == b && d b == a
sumToupleList :: (Integral a) => [(a,a)] -> a
sumToupleList list = sum $ map (\x -> fst x + snd x) list
main :: IO()
main = print $ sumToupleList $ listAmicableNumbers 10000
-- unused:
-- lists all proper Divisors of n sorted
listProperDivisors' :: (Integral a) => a -> [a]
listProperDivisors' 1 = [1]
listProperDivisors' n = quicksort $ 1 : (filter (\x -> x /= n) $ delDuplicates $ map product (subsets $ primefactors n))
-- sorts a list of list based on the length of the sublists
quicksort :: (Ord a) => [a] -> [a]
quicksort [] = []
quicksort (x:xs) =
let smallerSorted = quicksort [a | a <- xs, a <= x]
biggerSorted = quicksort [a | a <- xs, a > x]
in smallerSorted ++ [x] ++ biggerSorted