Project Euler Problem 33 asks us to find a particular pattern of fraction which satisfies several characteristics:
- It is less than one.
- It has two digits in both numerator and denominator.
- You can simplify the fraction correctly by canceling a single digit from both numerator and denominator.
- It is not a trivial fraction like (30/50).
My first attempt had the right idea, but the implementation has flaws because I tried to manage the numerator and denominator separately.
(defn as-digits [num] (map #(Character/getNumericValue %) (str num))) (defn gcd [a b] (if (zero? b) a (recur b (mod a b)))) (defn lcm [a b] (/ (* a b) (gcd a b))) (defn curious-frac? [num den] (let [n (as-digits num) d (as-digits den)] (and (= (second n) (first d)) (not (zero? (first n))) (not (zero? (second d))) (= (/ (first n) (second d)) (/ num den)) (< (/ num den) 1)))) (defn reduce-fraction [[n d]] (let [g (gcd n d)] [(/ n g) (/ d g)])) (defn euler-33  (let [fracs (for [num (range 10 100) den (range num 100) :when (curious-frac? num den)] [num den])] (reduce-fraction [(reduce * (map first fracs)) (reduce * (map second fracs))]))) (time (euler-33))
Compare this to bibi’s nice solution from clojure-euler:
(defn non-trivial?[n d] (let [x (quot n 10) y (rem n 10) u (quot d 10) v (rem d 10)] (cond (zero? v) false (and (= y u) (= (/ x v) (/ n d))) true :else false))) (defn euler-33-bibi  (let [fracs (for [n (range 10 99) d (range (inc n) 100) :when (non-trivial? n d)] (/ n d))] (.denominator (reduce * fracs))))
Lesson learned: don’t ignore the built-in data types like I did! Follow bibi’s example and let clojure manage your fractions automatically for you!