Project Euler Problem 37

Ivar Thorson bio photo By Ivar Thorson

One thing I learned during the course of completing problem 37 is that I have been using the wrong definition of prime? in previous problems. Technically, the number 1 is not in fact prime, yet the old definition of prime? would treat it as if it were.

The first bit of (working) code that I wrote looked like this and reused old code for prime? and as-digits.

(defn as-int [coll]
  (Integer/parseInt (apply str coll)))

(defn r-truncatable-prime? [n]
  (cond
   (= n 1)  false
   (< n 10) (prime? n)
   (prime? n) (recur (as-int (butlast (as-digits n))))
   true false))

(defn l-truncatable-prime? [n]
  (cond
   (= n 1)  false
   (< n 10) (prime? n)
   (prime? n) (recur (as-int (rest (as-digits n))))
   true false))

(defn lr-truncatable-prime? [n]
  (and (l-truncatable-prime? n)
       (r-truncatable-prime? n)))

(defn euler-37 []
  (reduce + (take 11 (filter lr-truncatable-prime? (iterate inc 10)))))

Repetition in code really bugs me because it’s easy to introduce bugs if I accidentally update one function but not it’s companion, so let’s improve the above definition a little and make it self-contained:

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

(defn prime? [n]
  (if (> 2 n)
    false
    (not-any? #(zero? (rem n %)) (take-while #(<= (* % %) n) primes))))

(defn as-digits [num]
  (map #(Character/getNumericValue %) (str num)))

(defn as-int [coll]
  (Integer/parseInt (apply str coll)))

(defn lr-truncatable-prime? [n]
  (let [trunc-prime? (fn [f n]
                (cond
                 (< n 10) (prime? n)
                 (prime? n) (recur f (as-int (f (as-digits n))))
                 true false))]
    (and (trunc-prime? butlast n)
         (trunc-prime? rest n))))

(defn euler-37 []
  (reduce + (take 11 (filter lr-truncatable-prime? (iterate inc 10)))))

I think that is remarkably readable. See you tomorrow!