From: livingcosmos.org
Subject: cartesian cross products?
Date: 
Message-ID: <52fb6d96-b742-4495-a8e2-b4307a9b0cb7@i29g2000prf.googlegroups.com>
How can you generate the cartesian cross product of a list of
sequences?

There is an old post which supposedly shows how to generate cartesian
cross products:

http://groups.google.com/group/comp.lang.lisp/browse_thread/thread/b7584279141237e2/c1b75ef0be1b26e4?lnk=gst&q=cross+product#c1b75ef0be1b26e4

But it generates really unusual output:

(defun x-prod (lsts)
  (labels ((rec (n acc)
                (cond ((< n 0) acc)
                      (t (rec (1- n)
                              (mapcan #'(lambda (e)
                                          (mapcar #'(lambda (x-prod)
                                                      (cons e x-
prod))
                                                  acc))
                                      (nth n lsts)))))))
    (if (null (cdr lsts))
        lsts
      (rec (- (length lsts) 2)
           (mapcar #'list (car (last lsts)))))))


(defun iota (x)
  (loop for i from 0 below x collect i))

(x-prod (list (iota 2) (iota 3) '(a b c)))



CL-USER> (x-prod (list (iota 2) (iota 3) (iota 4)))
((0 0 . #1=(0)) (0 0 . #2=(1)) (0 0 . #3=(2)) (0 0 . #4=(3)) (0 1 .
#1#) (0 1 . #2#) (0 1 . #3#) (0 1 . #4#) (0 2 . #1#) (0 2 . #2#) ...)

From: Rainer Joswig
Subject: Re: cartesian cross products?
Date: 
Message-ID: <joswig-87089B.15260317122007@news-europe.giganews.com>
In article 
<····································@i29g2000prf.googlegroups.com>,
 "livingcosmos.org" <········@gmail.com> wrote:

> How can you generate the cartesian cross product of a list of
> sequences?
> 
> There is an old post which supposedly shows how to generate cartesian
> cross products:
> 
> http://groups.google.com/group/comp.lang.lisp/browse_thread/thread/b7584279141237e2/c1b75ef0be1b26e4?lnk=gst&q=cross+product#c1b75ef0be1b26e4
> 
> But it generates really unusual output:
> 
> (defun x-prod (lsts)
>   (labels ((rec (n acc)
>                 (cond ((< n 0) acc)
>                       (t (rec (1- n)
>                               (mapcan #'(lambda (e)
>                                           (mapcar #'(lambda (x-prod)
>                                                       (cons e x-
> prod))
>                                                   acc))
>                                       (nth n lsts)))))))
>     (if (null (cdr lsts))
>         lsts
>       (rec (- (length lsts) 2)
>            (mapcar #'list (car (last lsts)))))))
> 
> 
> (defun iota (x)
>   (loop for i from 0 below x collect i))
> 
> (x-prod (list (iota 2) (iota 3) '(a b c)))
> 
> 
> 
> CL-USER> (x-prod (list (iota 2) (iota 3) (iota 4)))
> ((0 0 . #1=(0)) (0 0 . #2=(1)) (0 0 . #3=(2)) (0 0 . #4=(3)) (0 1 .
> #1#) (0 1 . #2#) (0 1 . #3#) (0 1 . #4#) (0 2 . #1#) (0 2 . #2#) ...)

Try with *print-circle* set to NIL.

-- 
http://lispm.dyndns.org/
From: Maciej Katafiasz
Subject: Re: cartesian cross products?
Date: 
Message-ID: <fk68ui$6k0$2@news.net.uni-c.dk>
Den Mon, 17 Dec 2007 05:56:09 -0800 skrev livingcosmos.org:

[snip]

I am curious as to how exactly you choose the nick/handle/name you write 
under. Do you do something like this?

(use-package :sb-md5)

(defvar *names* '("livingcosmos.org" "metaperl" "redick.metaperl.com"))

(defun choose-name (&optional (names *names*))
  (let* ((len (length names))
         (time (get-universal-time))
         (index (reduce '+ (md5sum-string (princ-to-string time)))))
    (elt names (mod index len))))

Cheers,
Maciej
From: livingcosmos.org
Subject: Re: cartesian cross products?
Date: 
Message-ID: <3644d13e-b887-4a69-9753-6ee7d8745ddf@e23g2000prf.googlegroups.com>
On Dec 17, 11:42 am, Maciej Katafiasz <········@gmail.com> wrote:
> Den Mon, 17 Dec 2007 05:56:09 -0800 skrev livingcosmos.org:
>
> [snip]
>
> I am curious as to how exactly you choose the nick/handle/name you write
> under.

I use google's web api to post here. I think one browser has one nick
and another has another :)

> Do you do something like this?
>

no, no programming involved. I miss my days of Gnus though. Perhaps I
should get back into Sylpheed claws or something better than just web
posting. Sigh.
From: Maciej Katafiasz
Subject: Re: cartesian cross products?
Date: 
Message-ID: <fk7s2c$aj0$1@news.net.uni-c.dk>
Den Mon, 17 Dec 2007 21:14:14 -0800 skrev livingcosmos.org:

>> Do you do something like this?
>>
> no, no programming involved. I miss my days of Gnus though. Perhaps I
> should get back into Sylpheed claws or something better than just web
> posting. Sigh.

That was a subtle poke at the randomness of it :). I feel your pain 
though, I was very happy to find out my ISP carried a news server that 
allowed me to post to c.l.l. Have you checked if yours doesn't?

Cheers,
Maciej
From: Alex Mizrahi
Subject: Re: cartesian cross products?
Date: 
Message-ID: <4767c723$0$90270$14726298@news.sunsite.dk>
 ??>> no, no programming involved. I miss my days of Gnus though. Perhaps I
 ??>> should get back into Sylpheed claws or something better than just web
 ??>> posting. Sigh.

 MK> That was a subtle poke at the randomness of it :). I feel your pain
 MK> though, I was very happy to find out my ISP carried a news server that
 MK> allowed me to post to c.l.l. Have you checked if yours doesn't?

even if he's doesn't there is news.sunsite.dk and plenty of other free. 
From: Kaz Kylheku
Subject: Re: cartesian cross products?
Date: 
Message-ID: <fd54b474-dfc1-4a7b-b515-3b05992d11b2@d4g2000prg.googlegroups.com>
On Dec 17, 5:56 am, "livingcosmos.org" <········@gmail.com> wrote:
> How can you generate the cartesian cross product of a list of
> sequences?

It's just called the Cartesian product.

How can you generate it? Well, for the binary case, you pair every
element in the first set, with every element in the second set, in
every possible way, and produce the set of these pairs.

Since you want this for sequences, you have to handle eight cases:

  list X list -> list
  list X vector -> list
  vector X list -> list
  vector X vector -> list

and the other four where the output is a vector.

A (binary) Cartesian product over lists only,  list X list -> list,
can be done like this:

 (defun cartesian (x y)
   (loop for xi in x
         appending (loop for yi in y
                         collecting (list xi yi))))


If you want to extend this to the N-ary Cartesian product, you can
rewrite the function above like this, and rename it:

 (defun cartesian-binary (x y)
   (loop for xi in x
         appending (loop for yj in y
                         collecting
                           (cond
                             ((and (listp xi) (listp yj)) (append xi
yj))
                             ((listp xi) (append xi (list yj)))
                             ((listp yj) (cons xi yj))
                             (t (list xi yj))))))

At the core are some cases which break open and re-combine tuples, as
necessary. This is slightly broken now, since now we can't have sets
of sets. This is due to the ambiguity of using lists as both sets and
tuples. (We could use vectors for tuples and lists for sets to fix the
problem).

But anyway, this gives us the ability to handle sets containing
tuples, which is important because the set containing the empty tuple
is the identity element:

  (cartesian-binary '(()) '(1 2 3)) -> ((1) (2) (3))

and also

  (cartesian-binary '(()) '((1) (2) (3))) -> ((1) (2) (3))

Scalar elements and 1-tuples are considered the same.

We can define the nullary Cartesian product---the Cartesian product
with no arguments---as producing the identity element.

And so we can now write CARTESIAN using REDUCE over CARTESIAN-BINARY,
using :INITIAL-VALUE to induce from identity:

(defun cartesian (&rest sets)
  (reduce #'cartesian-binary lists :initial-value '(())))

There you go.
From: vanekl
Subject: Re: cartesian cross products?
Date: 
Message-ID: <feb8f75d-d178-4bba-b8d5-e8b53c1727d3@w40g2000hsb.googlegroups.com>
you also may be interested in Norvig's solution on p.47 of PoAIP