Project Euler Problem 80

Ivar Thorson bio photo By Ivar Thorson

It took us until the 80th problem to find one, but we finally found an ugly wart in Clojure 1.2: big square roots. At the time of writing, it does not properly accommodate bigdec numbers. Look at this ugly behavior:

(expt 12 34)       ;; 4922235242952026704037113243122008064 ... a bignum.
(expt 12 (/ 34))   ;; 1.0758225047262997                    ... a double!
(with-precision 100 (expt 12 (/ 34))) ;;  1.0758225047262997... still a double!

Anyway, as I borrowed a little code to quickly implement a big-sqrt function but since I am not sure about the copyright of the code in question, I leave that function as an exercise to the reader. Accomplishing the task via Java libraries is another option.

With the big-sqrt function out of the way, the rest of this problem was extremely straightforward.

(use '[clojure.contrib.math :only (sqrt expt)])

(defn big-sqrt [n]
  (with-precision 150 (exercise-for-the-reader)))

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

(defn hundred-digit-sum [num]
  (reduce + (take 100 (as-digits num))))

(defn square? [n] (= n (* (int (sqrt n)) (int (sqrt n)))))

(defn euler-80 []
  (->> (for [n (range 1 101)
             :when (not (square? n))]
         (hundred-digit-sum (big-sqrt (bigdec n))))
       (reduce +)))

(time (euler-80)) ;; "Elapsed time: 92.808923 msecs"