munk
munk

Reputation: 12983

Common Lisp function returning the wrong value

I'm trying the project euler problems to learn common lisp and I'm stuck pretty early. On problem 1, the question is the sum of integers from 1 to 1000. I think the code below should do it, but it always returns the value of end (if it's mod 3 or mod 5) or 0 instead.

(defun mod3or5 (n)                                                                 
  (cond                                                                            
    ((equal (mod n 5) 0) n)                                                        
    ((equal (mod n 3) 0) n)                                                        
    (0))))                                                                         

(defun mod-sum (start end)                                                         
  (cond                                                                            
    ((equal start end) (mod3or5 start))                                            
    (+ (mod3or5 start) (mod-sum (+ start 1) end)))) 

For example

(mod-sum 1 9)
=> 9
(mod-sum 1 8)
=> 0

I would expect the answers to be 23 and 14 respectively.

Upvotes: 0

Views: 204

Answers (2)

user797257
user797257

Reputation:

I've posted this before, but it was in Scheme, so I decided to rewrite it in a bit, using loop for a change:

(defun euler-1 ()
  (loop with x = (list 3 2 1 3 1 2 3)
     for i in (nconc x x)
     while (< (+ steps i) 1000)
     summing i into steps
     summing steps into result
     finally (return result)))

This is how you could do it, avoiding modulo'ing (because it is expensive). You would also step 2 numbers on average (skipping those you don't have to add).

Upvotes: 0

sepp2k
sepp2k

Reputation: 370132

Each form given to cond has the form (condition exp1 ... expn). If condition is true, it will evaluate all the expressions and return the value of expn. If condition is false, it will continue with the next form.

Your last form is this: (+ (mod3or5 start) (mod-sum (+ start 1) end)). So here + is the condition (which will always be true because + is a function and thus not nil), (mod3or5 start) is the first expression (which will be evaluated, but not returned) and (mod-sum (+ start 1) end) is the last expression (which will be evaluated and then returned).

"Else branches" in cond are implemented by choosing t as the condition. So your last form should look like this:

(t (+ (mod3or5 start) (mod-sum (+ start 1) end)))

Upvotes: 5

Related Questions