Project Euler Problem 21 asked us to find the sum of all pairs of amicable numbers under 10000. My initial solution was relatively straightforward:
(defn proper-divisors [n]
(filter #(zero? (mod n %)) (range 1 (+ 1 (/ n 2)))))
(defn amicable-to [n]
(reduce + (proper-divisors n)))
(defn amicable-pair [n]
(let [d (amicable-to n)
e (amicable-to d)]
(if (and (not (= n d))
(= n e))
[n d]
nil)))
(defn euler-21 []
(reduce + (map first (remove nil? (map amicable-pair (range 1 10000))))))
(euler-21)
But that should probably be cleaned a little bit to better capture the essence of the problem:
(defn proper-divisors [n]
(filter #(zero? (mod n %)) (range 1 (+ 1 (/ n 2)))))
(defn amicable-to [n]
(reduce + (proper-divisors n)))
(defn amicable? [n]
(let [m (amicable-to n)]
(and (not (= n m))
(= n (amicable-to m)))))
(defn euler-21 []
(reduce + (filter amicable? (range 1 10000))))
(euler-21)
Performance isn’t particularly great because proper-divisors
uses a terribly naive algorithm. When we get to problem 23 – which also uses proper-divisors
– I expect that we will need to find a faster algorithm.