sumlispcommon-lisp

Basic Lisp function - sum of even minus sum of odd


I'm trying to write a function which takes as parameter a List and calculates the sum of even numbers minus the sum of odd numbers. Here is my implementation but I have no clue why it is not working as expected, could you give me any hints about whats wrong?

(defun sumEvenOdd (R)
  (cond
    ((NULL R) 0)
    ((and (ATOM (CAR R)) (= (mod (CAR R) 2) 0))
              (+ (CAR R) (sumEvenOdd (CDR R))))
    ((and (ATOM (CAR R)) (not (= (mod (CAR R) 2) 0)))
              (- (CAR R) (sumEvenOdd (CDR R)) ))
    ((LISTP (CAR R)) (sum (sumEvenOdd  (CAR R)) (sumEvenOdd  (CDR R))))
    (T  (sumEvenOdd  (CDR R)))
  )
)

Solution

  • Regarding the code algorithm, it fails because how the math is being done. How the code is now, this the evaluation being done with the list (list 1 2 3 4 5) is (- 1 (+ 2 (- 3 (+ 4 (- 5 0))))) that equals 5. What we were expecting was (2+4)-(1+3+5) that equals -3. What's wrong? Basically the sum operation in math is commutative, while the subtraction operation is not. 1+5 and 5+1 is the same. 1-5 and 5-1 is not. This reflects on the code on the last operation where 5 is being subtracted 0.

    The simplest solution is to adjust the operation order, switching the arguments.

    (defun sumEvenOdd (R)
      (cond
        ((NULL R) 0)
        ((and (ATOM (CAR R)) (= (mod (CAR R) 2) 0))
                  (+ (sumEvenOdd (CDR R)) (CAR R)))
        ((and (ATOM (CAR R)) (not (= (mod (CAR R) 2) 0)))
                  (- (sumEvenOdd (CDR R)) (CAR R)))
      )
    )
    

    That way the evaluation will be: (- (+ (- (+ (- 0 1) 2) 3) 4) 5) that equals -3.