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)))
)
)
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.