This is a read-only archive of lispforum.com. The forum was locked to new users and posts and is preserved here as static HTML from a database snapshot taken on 2019-09-07.

mapcar or notmapcar

12 posts · 2324 views

hi,im trying to get the following:
the input is a list of numbers (integers eg. (1 2 3 4) (5 6 7 8)) and the expected output is ((1*5)+(2*6)+(3*7)+(4*8))/(the sum of the second list).
is there a non-recursive way of solving it?


> (mapcar #'list '(1 2 3 4) '(5 6 7 8))
((1 5) (2 6) (3 7)(4 8))

i was thinking about mapcar, which would do the trick with a little tweaking, but how?
any ideas?
thanks

Re: mapcar or notmapcar

Yeah, you want MAPCAR. What you do not want is #'LIST. ;)
You'll also need one or two REDUCEs (or APPLYs) to get the sums.
"If you want to improve, be content to be thought foolish and stupid." -Epictetus

Re: mapcar or notmapcar

Using MAPCAR and REDUCE is fine. As an alternative approach, you could LOOP.
(defun notmapcar (list1 list2)
  "(list1 x list2) / Sum(list2)"
  (if (= (length list1) (length list2))
      (loop for val1 in list1
            and val2 in list2
            sum (* val1 val2) into num
            sum val2 into den
            finally (return (/ num den)))
      (error "The lists are not equal in length.")))
There are many ways to iterate in Common Lisp.

Edit: I was about to close down lisp when I just couldn't resist write a version with MAPCAR. It's not totally functional, but it only traverses the lists once.
(defun tomapcar (list1 list2)
  "(list1 x list2) / Sum(list2)"
  (let ((num 0)
        (den 0))
    (mapcar (lambda (n1 n2)
              (incf num (* n1 n2))
              (incf den n2))
            list1
            list2)
    (/ num den)))

~ Tom
Thomas M. Hermann
Odonata Research LLC
http://www.odonata-research.com/
http://www.linkedin.com/in/thomasmhermann

Re: mapcar or notmapcar

Duke wrote:Yeah, you want MAPCAR. What you do not want is #'LIST. ;)
What's wrong with #'list?

Re: mapcar or notmapcar

Tordmor wrote:
Duke wrote:Yeah, you want MAPCAR. What you do not want is #'LIST. ;)
What's wrong with #'list?
It does not do what he wants ;)

Re: mapcar or notmapcar

(defun operation (f-list s-list)
  (/ (reduce #'+ (mapcar #'* f-list s-list)) (reduce #'+ s-list)))

(operation '(1 2 3 4) '(5 6 7 8))  ;; gives 35/13
Need an online wiki database? My Lisp startup http://www.formlis.com combines a wiki with forms and reports.

Re: mapcar or notmapcar

Warren, is there a way to get decimals as a result instead of a fraction?

Re: mapcar or notmapcar

You can use the function FLOAT to convert a number (rational or integer) into a float.

Re: mapcar or notmapcar

Why would you want floats/decimal numbers? You could opt to use the more accurate rational numbers throughout your code and then use format's "~f" operator to print the result as a floating point number.
Need an online wiki database? My Lisp startup http://www.formlis.com combines a wiki with forms and reports.

Re: mapcar or notmapcar

Warren Wilkinson wrote:Why would you want floats/decimal numbers?
Depends on the code. Floats will generally be handled with greater performance by the hardware; rationals are Lisp-only concepts that have to be manipulated in software, with many extra steps. But as you point out, rationals will keep better precision through a many-step calculation.
Cheers, Dave
Slowly but surely the world is finding Lisp. http://www.findinglisp.com/blog/

Re: mapcar or notmapcar

Rationals also might grow up a lot (in used space) if you use lots of multiplications.

Re: mapcar or notmapcar

gugamilare wrote:Rationals also might grow up a lot (in used space) if you use lots of multiplications.
Yes, but if I remember right, implementations are required to reduce them if possible. In other words, they might be large, but not necessarily naively large.
Cheers, Dave
Slowly but surely the world is finding Lisp. http://www.findinglisp.com/blog/