Page 1 of 1

Pairing elements from list - MAPCAR version

Posted: Wed Jan 07, 2009 1:03 pm
by Ajschylos
Hi everybody,
I've started learning LISP again after several unsuccessful attempts, but now I gain some progress.

I am stuck with the problem:
Input: list of consecutive primes i.e. '(2 3 5 7 11)
Output: list of their pairwise products without duplication '(4 6 10 14 22 9 15 21 33 25 35 55 49 77 121)
I can imagine imperative solution with do-list or so.
Recursive solution is also very simple:

Code: Select all

(defun p-mul (l)
"Simple recursive version
 Input: List of different primes.
 Returns: List of pairwise multiplied elements of list l with no  duplicates"

  (if (null (rest l)) 
      (list (* (car l) (car l))) 
      (append (mapcar #'(lambda (x) (* x (first l))) 
                      l) 
              (p-mul (cdr l)))
      )
  )
Works pretty well, but I can't do it with using mapcar's, maplist's , and possibly other members of the family.

My last most successful solution is:

Code: Select all

(defun pair-mult (l)
"MAP___ version
 Input: List of different primes.
 Returns: List of pairwise multiplied elements of list l with no  duplicates"

(maplist #'(lambda (sub)  
        (mapcar #'(lambda (y x) (* x y))
                    sub l))

                 l)

)



Which applied to the list '(2 3 5 7 11) gives: ((4 9 25 49 121) (6 15 35 77) (10 21 55) (14 33) (22)) an awfully nested answer.

I don't want to 'flatten' this answer, I am looking for an elegant map***'s expression.

Does it exist?

Adam.

Re: Pairing elements from list - MAPCAR version

Posted: Wed Jan 07, 2009 6:28 pm
by nuntius
Replace the MAPLIST with MAPCON and the wynik with nil.

Re: Pairing elements from list - MAPCAR version

Posted: Wed Jan 07, 2009 10:46 pm
by Ajschylos
I am very sorry nuntius, the code I posted earlier works of corsue if "wynik" is global variable,
now I changed code so that function should return the list. That was my mistake. Adam.

Re: Pairing elements from list - MAPCAR version

Posted: Thu Jan 08, 2009 8:16 pm
by Kohath
If you're still interested, here's another way of doing it, also using curry for full flavour :D:

Code: Select all

(mapcon #'(lambda (sub)
            (mapcar (curry #'* (car sub)) sub))
        l)
It does it in the same order of the results that you originally posted.

P.S. Nice pickup on mapcon - those names confuse me every time...

Re: Pairing elements from list - MAPCAR version

Posted: Fri Jan 09, 2009 6:13 am
by Ajschylos
Thank you, this is a piece of beautiful code indeed.
I've found solution very similar:

Code: Select all

(defun par-mul (l)

 (mapcon #'(lambda (sub) 
             (mapcar #'(lambda (x) (* x (first sub))) 
                     sub)) 
         l)
)
I must analyze the difference between two approaches.
Thank's a lot. Adam.