Bogdan Molinger
Bogdan Molinger

Reputation: 341

Adding two lists

I want to add two lists : (1 2 3) and (5 3 4) should yield (6 5 7).
The function should add the elements on the corresponding position, so even if I would have (9 1 2) + ( 5 2 6) , it should yield (14 3 8).
My function

(defun add(l r)
    (setf return-value '())
        (loop for i from 0 to (- (length l) 1)
            do (setf return-value (cons (+(nth i l)(nth i r)) return-value))
        )
    (reverse return-value)
)

How could I create a simmilar function which would subtract the lists ?

Upvotes: 0

Views: 3130

Answers (2)

Joshua Taylor
Joshua Taylor

Reputation: 85813

Polynomial arithmetic

This seems like a follow up to your previous question, Decompose a list of numbers into digits,. There, you had a list of digits numbers, and they were the ai of a polynomial of the form

i=0… 10iai

where the n numbers in your list are the values of a0 to an-1, and everything after that is presumed to be zero. You were asking for a way to normalize the values such that each ai was in the range [0,9]. My answer to that question showed a few ways to do that.

Now, once you view numbers as a polynomial of this form, it's easy to see that you can simply piecewise add and subtract coefficients to the get the right, if not yet normalized, coefficients of the sum or difference. E.g.,

378 = 8 + 7×10 + 3×100→ (8 7 3)
519 = 9 + 1×10 + 5×100→ (9 1 5)

The sum is simply

(8+9) + (7+1)×10 + (3+5)×100 →(mapcar '+ x y) (17 8 8) →(number->digits (digits->number …)) (7 9 8)

The difference is simply

(8-9) + (7-1)×10 + (3-5)×100 →(mapcar '- x y) (-1 6 -2) →??? ???

What we don't have here is an appropriate normalization procedure. The one provided in the previous question doesn't work here. However, the list of digits is still correct, insofar as coefficients go, and the digits->number procedure produces the correct value of -141.

So, while you'll need to rethink what it means to show a list of digits for a negative number, you can do the correct type of addition and subtraction on your lists with the following, as long as both lists have the same length. If they don't have the same length, you'll need to pad the shorter one with zeros. A reimplementation of mapcar that supports this sort of operation might be useful here.

(defun sum (x y)
  (mapcar '+ x y))

(defun difference (x y)
  (mapcar '- x y))

Upvotes: 0

sds
sds

Reputation: 60004

If you are allowed to use the standard functions, then mapcar is your friend:

(mapcar #'+ '(1 2 3) (9 7 5))
==> (10 9 8)

Similarly for -.

Your function suffers from quadratic performance - you should not be using nth. You should also bind return-value with let. You should also use nreverse instead of reverse since you are constructing a fresh list anyway.

The more idiomatic way to write your function is

(defun addl (l r)
  (loop for x in l and y in r collect (+ x y)))

Upvotes: 3

Related Questions