Project Euler Problem 21

Ivar Thorson bio photo By Ivar Thorson

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.