4

I am doing the Project Euler challenge in Clojure and I want to find the sum of all the even numbers in a fibonacci sequence up to a certain number.

The code for a function that does this is below. I know there are quicker and easier ways of doing this, I am just experimenting with recursion using loop and recur. However the code doesn't seem to work it never returns an answer.

(defn fib-even-sum [upto]
  (loop [previous 1 nxt 1 sum 0]
    (if (or (<= upto 1) (>= nxt upto))
     sum)
    (if (= (mod nxt 2) 0)
       (recur nxt (+ previous nxt) (+ sum nxt))
       (recur nxt (+ previous nxt) sum))))

I was not sure if I could do recur twice in the same loop or not. I'm not sure if this is causing the problem?

4
  • I was looking into that predicate. I'm going to change the code to use it. Thanks for pointing it out. Commented Jun 23, 2011 at 13:54
  • 2
    there is a fibs in 'clojure.contrib.lazy-seqs which is quite fast. With that, the problem can be expressed like this: (reduce + (filter #(even? %) (take-while #(< % 4000000) (fibs)))) .. some of the other Euler Problems can be done as one-liners as well, enjoy! :-) Commented Jun 24, 2011 at 18:24
  • Just an alternative (know you weren't looking for one, so it's in a comment!) (def fibo (map second (iterate (fn [[x y]] [y (+ x y)]) [0 1]))) Commented Jun 25, 2011 at 23:46
  • 1
    @IsaacHodes Yikes, don't do that. If you def it at the top-level, it can never get GCed. Instead, (defn fib0 [] (map ...)) and call fib0 whenever you need a new copy of the sequence. Commented Nov 27, 2011 at 23:55

1 Answer 1

5

You have a misplaced closing paren in the first IF (after sum)...

(defn fib-even-sum [upto]
  (loop [previous 1 nxt 1 sum 0]
    (if (or (<= upto 1) (>= nxt upto))
        sum
        (if (= (mod nxt 2) 0)
           (recur nxt (+ previous nxt) (+ sum nxt))
           (recur nxt (+ previous nxt) sum)))))

Now it works and fast

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks. I see the problem. Works great now.
This is a common problem for new lisp coders, by the way. If I were writing this, I'd replace the (if a x (if b y z)) pattern with a use of cond: (cond a x, b y, :else z). But of course you should learn at your own pace, and not worry about form if you're still learning the function.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.