function like Mathematica's Tuples
- Subject: function like Mathematica's Tuples
- From: John Lapeyre
- Date: Wed, 19 May 2010 02:08:08 +0200
> Sets can be converted into lists by means of listify.
>
> (%i1) tuples(lis, n) :=
> block(
> [ len_lis, aux_lis, aux_set, cart_prod],
> len_lis : length(lis),
> aux_lis : makelist(k,k,1,len_lis),
> aux_set : setify(aux_lis),
> cart_prod : apply(cartesian_product, makelist(aux_set,k,1,n)),
> subst(map("=", aux_lis, lis), listify(cart_prod)) ) $
Thats slick!
If you want more complicated code, the following will do the
same, as well as the following that Mma Tuples will do.
Tuples([[a, b], [1, 2, 3, 4], [x]]);
[[a,1,x],[a,2,x],[a,3,x],[a,4,x],[b,1,x],[b,2,x],[b,3,x],[b,4,x]];
Tuples(f[a,b,c],2);
[f[a,a],f[a,b],f[a,c],f[b,a],f[b,b],f[b,c],f[c,a],f[c,b],f[c,c]];
Tuples([f[a,b,c],f[0,1]]);
[f[a,0],f[a,1],f[b,0],f[b,1],f[c,0],f[c,1]];
Of course, the code above could be easily modified to do this as well.
--John
-----------
(defmfun |$Tuples| (lis &rest num &aux inds olis lims head)
(cond ( (eq nil num)
(setq lis (rest lis))
(setq num (length lis))
(setq head (first (first lis)))
(setq lis (mapcar #'rest lis))
(setq lims (reverse (mapcar #'length lis)))
(setq inds (mixima-make-inds num))
(loop do
(setq olis (cons (cons head (mapcar #'(lambda (x y) (nth x y)) (reverse inds) lis)) olis))
(cond ( (inc-inds inds lims) (loop-finish))))
(setq olis (cons '(mlist) (reverse olis)))
olis)
(t
(setq num (first num))
(setq head (first lis))
(setq lis (rest lis))
(setq inds (mixima-make-inds num))
(setq lims (make-list num :initial-element (length lis)))
(loop do
(setq olis (cons (cons head (mapcar #'(lambda (x) (nth x lis)) (reverse inds))) olis))
(cond ( (inc-inds inds lims) (loop-finish))))
(setq olis (cons '(mlist) (reverse olis)))
olis)))
(defun inc-inds (inds lims &aux (n (- (length inds) 1)) (roll nil) )
(loop for i from 0 to n do
(setf (elt inds i) (+ (elt inds i) 1))
(cond ((eq (elt inds i) (elt lims i))
(cond ( (eq i n) (setq roll t)))
(loop for j from 0 to i do
(setf (elt inds j) 0)))
(t (loop-finish))))
roll)
(defun mixima-make-inds (n)
(make-list n :initial-element 0))