I am learning Clojure and trying to solve Project's Euler (http://projecteuler.net/) problems using this language. Second problem asks to find the sum of the even-valued terms in Fibonacci sequence whose values do not exceed four million.
I've tried several approaches and would find next one most accurate if I could find where it's broken. Now it returns 0. I am pretty sure there is a problem with take-while condition but can't figure it out.
(reduce +
(take-while (and even? (partial < 4000000))
(map first (iterate (fn [[a b]] [b (+ a b)]) [0 1]))))
user> ((partial < 4000000) 1)
false
Partial puts the static arguments first and the free ones at the end, so it's building the opposite of what you want. It is essentially producing #(< 4000000 %)
instead of #(< % 4000000)
as you intended, So just change the >
to <
:
user> (reduce +
(take-while (and even? (partial > 4000000))
(map first (iterate (fn [[a b]] [b (+ a b)]) [0 1]))))
9227464
or perhaps it would be more clear to use the anonymous function form directly:
user> (reduce +
(take-while (and even? #(< % 4000000))
(map first (iterate (fn [[a b]] [b (+ a b)]) [0 1]))))
9227464
Now that we have covered a bit about partial, let's break down a working solution. I'll use the thread-last macro ->>
to show each step separately.
user> (->> (iterate (fn [[a b]] [b (+ a b)]) [0 1]) ;; start with the fibs
(map first) ;; keep only the answer
(take-while #(< % 4000000)) ;; stop when they get too big
(filter even?) ;; take only the even? ones
(reduce +)) ;; sum it all together.
4613732
From this we can see that we don't actually want to compose the predicates evan?
and less-than-4000000 on a take-while
because this would stop as soon as either condition was true leaving only the number zero. Rather we want to use one of the predicates as a limit and the other as a filter.