Project Euler Problem 46

Ivar Thorson bio photo By Ivar Thorson

Problem 46 asks us to find the smallest composite number that can’t be written as a prime number plus twice a square.

My first attempt involved writing compositable? with the for construct. It works, but is inefficient.

(use '[clojure.contrib.lazy-seqs :only (primes)])

(def double-squares (map #(* 2 % %) (range)))

(defn compositable? [n]
  (true? (first (for [a (take-while #(>= n %) primes)
                      b (take-while #(>= (- n a) %) double-squares)
                      :when (= n (+ a b))]
                  true))))

(defn euler-46 []
  (first (remove compositable? (iterate #(+ 2 %) 3))))

(time (euler-46)) ;; "Elapsed time: 2674.650168 msecs"

Why the terrible performance? The for loop foolishly generates all possible combinations instead of just checking for valid combinations.

To check only valid combinations, we need to use our old friend prime?:

(defn prime? [n]
  (and (< 1 n)
       (not-any? #(zero? (rem n %)) (take-while #(<= (* % %) n) primes)))) 

(defn compositable? [n]
  (some #(prime? (- n %)) (take-while #(> n %) double-squares)))

(defn euler-46-revised []
  (first (remove compositable? (remove prime? (iterate #(+ 2 %) 3)))))

(time (euler-46-revised)) ;; "Elapsed time: 47.315354 msecs"

Ahh, that’s better.