From: John Thingstad
Subject: combinations not working
Date: 
Message-ID: <op.tlfna6e0pqzri1@pandora.upc.no>
This is a excerpt from my code:

--------------------------------------------------------------------------

(defun write-trace (body)
   (format *trace-output* "~&~A~%" body))

(defmacro output (body)
   `(progn
      ;(write-trace ',body)
      ,body))

(defun nrotate (vector start end)
   (rotatef (aref vector start) (aref vector end)))

(defun forall-combinations (vector function)
   "Compute the combinations on 'vector' and call 'function'
on each combination. 'function' is assumed to be a function that
takes a vector argument and does not modify this.
Note that the vector argument given to 'function' is volatile and must be  
copied
if it is stored."
   (check-type vector simple-vector)
   (check-type function function)
   (let ((length (length vector))
         (copy (copy-seq vector)))
     (labels ((recurse (index)
                (loop repeat (- length index) do
                  (if (< index (- length 2))
                      (recurse (1+ index))
                    (output (funcall function copy)))
                  (output (nrotate copy index (1+ index))))))
       (recurse 0)))
   (values))

(defun list->vector (list)
   (make-array (length list) :initial-contents list))

(defun vector->list (vector)
   (loop for element across vector collect element))

(defun print-combinations (sequence)
   "Output the combinations a line at a time to standard output.
'sequence' can be either a list or vector.
If 'sequence' is a vector prints as #(...), if it is a list (..)
ex. (print-combinations '(1 2)) prints
   1: (1 2)
   2: (2 1)"
   (check-type sequence (or simple-vector cons))
   (let ((count 0)
         (vector (if (listp sequence) (list->vector sequence) sequence))
         (seq-op (if (listp sequence) #'vector->list #'identity)))
     (flet ((display (vector)
              (incf count)
              (format t "~&~3d: ~A~%" count (funcall seq-op vector))))
       (forall-combinations vector #'display))))

--------------------------------------------------------------------------

Problem:
  1. The combinations are not computed right.
     To dumb to see what I am missing I guess.
     ex: (print-combinations '(1 2 3))
       1: (1 2 3)
       2: (1 3 2)
       3: (2 1 3)
       4: (2 3 1)
       5: (1 2 3)
       6: (1 3 2)
     What is wrong? Is there a better way?

  2. The macro output (with the ; removed) just prints the call verbatim.
     ex. (output (nrotate copy start (1+ start)) prints
         (nrotate copy start (1+ start))
     I would like it to resolve the variables.
     ex. (output (nrotate copy start (1+ start)) prints
     (nrotate #(1 2 3) 1 2)
     How do I do this?

-- 
Using Opera's revolutionary e-mail client: http://www.opera.com/mail/

From: Pascal Bourguignon
Subject: Re: combinations not working
Date: 
Message-ID: <874prcm1jf.fsf@thalassa.informatimago.com>
"John Thingstad" <··············@chello.no> writes:

> This is a excerpt from my code:
> [...]
>
> Problem:
>  1. The combinations are not computed right.
>     To dumb to see what I am missing I guess.
>     ex: (print-combinations '(1 2 3))
>       1: (1 2 3)
>       2: (1 3 2)
>       3: (2 1 3)
>       4: (2 3 1)
>       5: (1 2 3)
>       6: (1 3 2)
>     What is wrong? Is there a better way?

You don't put the rotated elements back in place.  The following work:

(defun permute (vector index action)
  (cond
    ((zerop index)  (funcall action vector))
    (t  (permute vector (1- index) action)
        (dotimes (i index)
          (rotatef (aref vector index) (aref vector i))
          (permute vector (1- index) action)
          (rotatef (aref vector index)  (aref vector i))))))

C/USER[830]> (permute #(1 2 3) 2 (function print))

#(1 2 3) 
#(2 1 3) 
#(3 1 2) 
#(1 3 2) 
#(1 2 3) 
#(2 1 3) 
NIL

If you remove the last ROTATEF, it gives results similar to  yours.


>  2. The macro output (with the ; removed) just prints the call verbatim.
>     ex. (output (nrotate copy start (1+ start)) prints
>         (nrotate copy start (1+ start))
>     I would like it to resolve the variables.
>     ex. (output (nrotate copy start (1+ start)) prints
>     (nrotate #(1 2 3) 1 2)
>     How do I do this?

(output `(nrotate ,copy ,start ,(1+ start)))

A better way is not to modify your source, and use TRACE (and UNTRACE
when you're done debugging).


-- 
__Pascal Bourguignon__                     http://www.informatimago.com/

"Debugging?  Klingons do not debug! Our software does not coddle the
weak."
From: John Thingstad
Subject: Re: combinations not working
Date: 
Message-ID: <op.tlfr6enppqzri1@pandora.upc.no>
On Sun, 31 Dec 2006 18:13:24 +0100, Pascal Bourguignon  
<···@informatimago.com> wrote:

>
> If you remove the last ROTATEF, it gives results similar to  yours.
>

Thanks! Yes I see it now..

>
>>  2. The macro output (with the ; removed) just prints the call verbatim.
>>     ex. (output (nrotate copy start (1+ start)) prints
>>         (nrotate copy start (1+ start))
>>     I would like it to resolve the variables.
>>     ex. (output (nrotate copy start (1+ start)) prints
>>     (nrotate #(1 2 3) 1 2)
>>     How do I do this?
>
> (output `(nrotate ,copy ,start ,(1+ start)))
>
> A better way is not to modify your source, and use TRACE (and UNTRACE
> when you're done debugging).
>
>

Not really what I asked for. I needs macro 'output' to generate

(output (nrotate copy start (1+ start)) =>
(progn
   (write-trace `(nrotate ,copy ,start ,(1+ start))
   (nrotate copy start (1+ start)))

I have:
(defmacro output (body)
   (let ((expr (append (list (first body))
                       (loop for element in (rest body)
                             collect `(#\, ,element)))))
   `(progn
      (write-trace (list #\` ,expr))
      ,body)))

which gives:

(PROGN
   (WRITE-TRACE (LIST #\` (NROTATE (#\, COPY) (#\, INDEX) (#\,  
(1+ INDEX)))))
   (NROTATE COPY INDEX (1+ INDEX)))

Which still isn't there. But it should give you a idea.

-- 
Using Opera's revolutionary e-mail client: http://www.opera.com/mail/
From: ········@gmail.com
Subject: Re: combinations not working
Date: 
Message-ID: <1167618292.403491.55120@s34g2000cwa.googlegroups.com>
John Thingstad wrote:
> This is a excerpt from my code:
>
> --------------------------------------------------------------------------
>
> (defun write-trace (body)
>    (format *trace-output* "~&~A~%" body))
>
> (defmacro output (body)
>    `(progn
>       ;(write-trace ',body)
>       ,body))
>
> (defun nrotate (vector start end)
>    (rotatef (aref vector start) (aref vector end)))
>
> (defun forall-combinations (vector function)
>    "Compute the combinations on 'vector' and call 'function'
> on each combination. 'function' is assumed to be a function that
> takes a vector argument and does not modify this.
> Note that the vector argument given to 'function' is volatile and must be
> copied
> if it is stored."
>    (check-type vector simple-vector)
>    (check-type function function)
>    (let ((length (length vector))
>          (copy (copy-seq vector)))
>      (labels ((recurse (index)
>                 (loop repeat (- length index) do
>                   (if (< index (- length 2))
>                       (recurse (1+ index))
>                     (output (funcall function copy)))
>                   (output (nrotate copy index (1+ index))))))
>        (recurse 0)))
>    (values))
>
> (defun list->vector (list)
>    (make-array (length list) :initial-contents list))
>
> (defun vector->list (vector)
>    (loop for element across vector collect element))
>
> (defun print-combinations (sequence)
>    "Output the combinations a line at a time to standard output.
> 'sequence' can be either a list or vector.
> If 'sequence' is a vector prints as #(...), if it is a list (..)
> ex. (print-combinations '(1 2)) prints
>    1: (1 2)
>    2: (2 1)"
>    (check-type sequence (or simple-vector cons))
>    (let ((count 0)
>          (vector (if (listp sequence) (list->vector sequence) sequence))
>          (seq-op (if (listp sequence) #'vector->list #'identity)))
>      (flet ((display (vector)
>               (incf count)
>               (format t "~&~3d: ~A~%" count (funcall seq-op vector))))
>        (forall-combinations vector #'display))))
>
> --------------------------------------------------------------------------
>
> Problem:
>   1. The combinations are not computed right.
>      To dumb to see what I am missing I guess.
>      ex: (print-combinations '(1 2 3))
>        1: (1 2 3)
>        2: (1 3 2)
>        3: (2 1 3)
>        4: (2 3 1)
>        5: (1 2 3)
>        6: (1 3 2)
>      What is wrong? Is there a better way?
>

Pascal already mentioned why the combinations aren't working...

In the big scheme of things, I think it would be probubly be much more
useful to make a macro that executed a body of code for every possible
permutation of the vector with a variable bound to it than a function
that applies a unary function to the vector for every possible
permutation...

this is how I would do it:

(defmacro with-permuting-vector ((var vector &optional return) &body
body)
  (let ((s (gensym)))
    `(let* ((,var ,vector)
	    (,s   (length ,var)))

      (labels ((rfn (start)
		 (if (= start ,s)
		     (progn ,@body)                ;Execute body
		     (do ((n start (incf n)))
			 ((>= n ,s))
		       (rotatef (svref ,var start) (svref ,var n))
		       (rfn (1+ start))
		       (rotatef (svref ,var start) (svref ,var n))))))
	(rfn 0)
	,return))))

CL-USER> (with-permuting-vector (v #(1 2 3) 'done)
	   (print v))

#(1 2 3)
#(1 3 2)
#(2 1 3)
#(2 3 1)
#(3 2 1)
#(3 1 2)
DONE
CL-USER>




>   2. The macro output (with the ; removed) just prints the call verbatim.
>      ex. (output (nrotate copy start (1+ start)) prints
>          (nrotate copy start (1+ start))
>      I would like it to resolve the variables.
>      ex. (output (nrotate copy start (1+ start)) prints
>      (nrotate #(1 2 3) 1 2)
>      How do I do this?
>

as for the output thing

(defun prepare-form (sexp)
  (if (listp sexp)
      `(list ',(prepare-form (first sexp))
	     ,@(mapcar #'prepare-form (rest sexp)))
      sexp))t

(defmacro output (&body body)
  `(progn
    (format t  "~{~&~A~}" ,`(list ,@(mapcar #'prepare-form body)))
    ,@body))

CL-USER> (macroexpand-1 '(output (foo x) (bar y) (baz (+ x y))))
(PROGN (FORMAT T "~{~&~A~}" (LIST (LIST 'FOO X) (LIST 'BAR Y) (LIST
'BAZ (LIST '+ X Y)))) (FOO X) (BAR Y) (BAZ (+ X Y)))
T
CL-USER> (with-permuting-vector (v #(1 2 3))
	   (output (print v)))
(PRINT #(1 2 3))
#(1 2 3)
(PRINT #(1 3 2))
#(1 3 2)
(PRINT #(2 1 3))
#(2 1 3)
(PRINT #(2 3 1))
#(2 3 1)
(PRINT #(3 2 1))
#(3 2 1)
(PRINT #(3 1 2))
#(3 1 2)
NIL
CL-USER>

hth, take care

Nick



> --
> Using Opera's revolutionary e-mail client: http://www.opera.com/mail/
From: Rainer Joswig
Subject: Re: combinations not working
Date: 
Message-ID: <C1BEA03C.6973F%joswig@lisp.de>
Am 01.01.2007 3:24 Uhr schrieb ·········@gmail.com" unter
<········@gmail.com> in
·······················@s34g2000cwa.googlegroups.com:

 
> 
> Pascal already mentioned why the combinations aren't working...
> 
> In the big scheme of things, I think it would be probubly be much more
> useful to make a macro that executed a body of code for every possible
> permutation of the vector with a variable bound to it than a function
> that applies a unary function to the vector for every possible
> permutation...

How would that be more useful? Why is a macro more useful than a function
in this case?

> 
> this is how I would do it:
> 
> (defmacro with-permuting-vector ((var vector &optional return) &body
> body)
>   (let ((s (gensym)))
>     `(let* ((,var ,vector)
>    (,s   (length ,var)))
> 
>       (labels ((rfn (start)
> (if (= start ,s)
>     (progn ,@body)                ;Execute body
>     (do ((n start (incf n)))
> ((>= n ,s))
>       (rotatef (svref ,var start) (svref ,var n))
>       (rfn (1+ start))
>       (rotatef (svref ,var start) (svref ,var n))))))
> (rfn 0)
> ,return))))
> 
> CL-USER> (with-permuting-vector (v #(1 2 3) 'done)
>   (print v))

So that is more useful than something like (permute-vector #(1 2 3) #'print)
? How?
From: John Thingstad
Subject: Re: combinations not working
Date: 
Message-ID: <op.tlg3oicupqzri1@pandora.upc.no>
On Mon, 01 Jan 2007 11:25:48 +0100, Rainer Joswig <······@lisp.de> wrote:

> Am 01.01.2007 3:24 Uhr schrieb ·········@gmail.com" unter
> <········@gmail.com> in
> ·······················@s34g2000cwa.googlegroups.com:
>
>
>
> So that is more useful than something like (permute-vector #(1 2 3)  
> #'print)
> ? How?
>

Let's write the macro using the functional version.

(defmacro with-permuting-vector ((var vector &optional return) &body body)
   `(let ((,var ,vector))
      (forall-combinations ,var (lambda (,var) ,@body ,return))))

I guess it is more a matter of taste.
Personally I would prefer not to have the dependecies generated by a macro  
if
I don't have to. Also consider the size of the replication of code going  
on there.

I am not that wild about calling it permutations by the way.
Consider:

(1 1 1)
(1 1 2)
...
(3 3 3)

That is the permutations of (1 2 3).

there are 3^3 = 27 permutations
which includes the 3! = 6 combinations.

-- 
Using Opera's revolutionary e-mail client: http://www.opera.com/mail/
From: John Thingstad
Subject: Re: combinations not working
Date: 
Message-ID: <op.tlhbvqfgpqzri1@pandora.upc.no>
On Mon, 01 Jan 2007 12:32:32 +0100, John Thingstad  
<··············@chello.no> wrote:

> (defmacro with-permuting-vector ((var vector &optional return) &body   
> body)
>    `(let ((,var ,vector))
>       (forall-combinations ,var (lambda (,var) ,@body ,return))))
>

Oops! The &optional argument was added as a afterthought without testing.
Looking at it is should be:

(defmacro with-permuting-vector ((var vector &optional return) &body  body)
    `(let ((,var ,vector))
       (forall-combinations ,var (lambda (,var) ,@body))
       ,return))

-- 
Using Opera's revolutionary e-mail client: http://www.opera.com/mail/
From: ········@gmail.com
Subject: Re: combinations not working
Date: 
Message-ID: <1167685777.258334.113640@s34g2000cwa.googlegroups.com>
Rainer Joswig wrote:
> Am 01.01.2007 3:24 Uhr schrieb ·········@gmail.com" unter
> <········@gmail.com> in
> ·······················@s34g2000cwa.googlegroups.com:
>
>
> >
> > Pascal already mentioned why the combinations aren't working...
> >
> > In the big scheme of things, I think it would be probubly be much more
> > useful to make a macro that executed a body of code for every possible
> > permutation of the vector with a variable bound to it than a function
> > that applies a unary function to the vector for every possible
> > permutation...
>
> How would that be more useful? Why is a macro more useful than a function
> in this case?
>
> >
> > this is how I would do it:
> >
> > (defmacro with-permuting-vector ((var vector &optional return) &body
> > body)
> >   (let ((s (gensym)))
> >     `(let* ((,var ,vector)
> >    (,s   (length ,var)))
> >
> >       (labels ((rfn (start)
> > (if (= start ,s)
> >     (progn ,@body)                ;Execute body
> >     (do ((n start (incf n)))
> > ((>= n ,s))
> >       (rotatef (svref ,var start) (svref ,var n))
> >       (rfn (1+ start))
> >       (rotatef (svref ,var start) (svref ,var n))))))
> > (rfn 0)
> > ,return))))
> >
> > CL-USER> (with-permuting-vector (v #(1 2 3) 'done)
> >   (print v))
>
> So that is more useful than something like (permute-vector #(1 2 3) #'print)
> ? How?

why add DO-LIST to the language if it already has MAPC? to avoid having
to type lambda... what if I want to use it in more than function. what
if I want to use the vector with a function that takes more than one
argument?

(defun scramble-to-pattern (vector pattern)
   (with-permuting-vector (v vector)
      (when (satisfies-pattern-p v pattern)
         (return-from scramble-to-pattern v))))

vs

(defun scramble-to-pattern (vector pattern)
  (permute-vector vector #'(lambda (x)
			     (when (satisfies-pattern-p x pattern)
			       (return-from scramble-to-pattern x)))))

on another note, the macro should probubly have been named
DO-PERMUTING-VECTOR not WITH-PERMUTING-VECTOR...
From: Rainer Joswig
Subject: Re: combinations not working
Date: 
Message-ID: <joswig-0A8399.23081901012007@news-europe.giganews.com>
In article <························@s34g2000cwa.googlegroups.com>,
 ········@gmail.com wrote:

> Rainer Joswig wrote:
> > Am 01.01.2007 3:24 Uhr schrieb ·········@gmail.com" unter
> > <········@gmail.com> in
> > ·······················@s34g2000cwa.googlegroups.com:
> >
> >
> > >
> > > Pascal already mentioned why the combinations aren't working...
> > >
> > > In the big scheme of things, I think it would be probubly be much more
> > > useful to make a macro that executed a body of code for every possible
> > > permutation of the vector with a variable bound to it than a function
> > > that applies a unary function to the vector for every possible
> > > permutation...
> >
> > How would that be more useful? Why is a macro more useful than a function
> > in this case?
> >
> > >
> > > this is how I would do it:
> > >
> > > (defmacro with-permuting-vector ((var vector &optional return) &body
> > > body)
> > >   (let ((s (gensym)))
> > >     `(let* ((,var ,vector)
> > >    (,s   (length ,var)))
> > >
> > >       (labels ((rfn (start)
> > > (if (= start ,s)
> > >     (progn ,@body)                ;Execute body
> > >     (do ((n start (incf n)))
> > > ((>= n ,s))
> > >       (rotatef (svref ,var start) (svref ,var n))
> > >       (rfn (1+ start))
> > >       (rotatef (svref ,var start) (svref ,var n))))))
> > > (rfn 0)
> > > ,return))))
> > >
> > > CL-USER> (with-permuting-vector (v #(1 2 3) 'done)
> > >   (print v))
> >
> > So that is more useful than something like (permute-vector #(1 2 3) #'print)
> > ? How?
> 
> why add DO-LIST to the language if it already has MAPC? to avoid having
> to type lambda... what if I want to use it in more than function. what
> if I want to use the vector with a function that takes more than one
> argument?
> 
> (defun scramble-to-pattern (vector pattern)
>    (with-permuting-vector (v vector)
>       (when (satisfies-pattern-p v pattern)
>          (return-from scramble-to-pattern v))))
> 
> vs
> 
> (defun scramble-to-pattern (vector pattern)
>   (permute-vector vector #'(lambda (x)
> 			     (when (satisfies-pattern-p x pattern)
> 			       (return-from scramble-to-pattern x)))))

Yep, that's called Functional Programming - programming with
functions. It is mostly clearer, better to debug, easier
to combinate, easier to write and so on. All IMHO. ;-)

> 
> on another note, the macro should probubly have been named
> DO-PERMUTING-VECTOR not WITH-PERMUTING-VECTOR...
From: Madhu
Subject: Re: combinations not working
Date: 
Message-ID: <m3mz52g5io.fsf@robolove.meer.net>
Helu

* Rainer Joswig <·····················@lisp.de> :

|> CL-USER> (with-permuting-vector (v #(1 2 3) 'done)
|>   (print v))
|
| So that is more useful than something like (permute-vector #(1 2 3) #'print)
| ? How?

Preference: I'd like to do

(loop for x being each permutation of #(1 2 3) 
      do print x)

But that is no excuse for not writing PERMUTE-VECTOR first and using
that to write the macro:

(defmacro for-as-permutation-do ((var bag &optional RESULT) &body body)
  (let ((body-name (gensym)))
    `(block nil
       (flet ((,body-name (,var) ,@body))
	 (PERMUTE-VECTOR ,BAG  #',body-name)
	 ,result))))

--
Madhu
From: John Thingstad
Subject: Re: combinations not working
Date: 
Message-ID: <op.tlg46p1lpqzri1@pandora.upc.no>
On Mon, 01 Jan 2007 03:24:52 +0100, <········@gmail.com> wrote:

1. Great. Hadn't thought of that. Your algorithm is a bit cleaner too.
Still think I'll stick with the functional form I had.

(defun nrotate (vector start end)
   (rotatef (svref vector start) (svref vector end)))

(defun forall-combinations (vector function)
   "Compute the combinations on 'vector' and call 'function'
on each combination. 'function' is assumed to be a function that
takes a vector argument and does not modify this.
Note that the vector argument given to 'function' is volatile and must be  
copied
if it is stored."
   (check-type vector simple-vector)
   (check-type function function)
   (let ((last (1- (length vector)))
         (copy (copy-seq vector)))
     (labels ((recurse (start)
                (if (= start last)
                    (funcall function copy)
                  (loop for index from start to last do
                        (nrotate copy start index) ;
                        (recurse (1+ start))
                        (nrotate copy start index)))))
       (recurse 0)))
   (values))

2.
> (defun prepare-form (sexp)
>   (if (listp sexp)
>       `(list ',(prepare-form (first sexp))
> 	     ,@(mapcar #'prepare-form (rest sexp)))
>       sexp))t
>
> (defmacro output (&body body)
>   `(progn
>     (format t  "~{~&~A~}" ,`(list ,@(mapcar #'prepare-form body)))
>     ,@body))
>

Ah! Seriously cool. Perhaps a bit too powerful though..
Consider in 'forall-combinations' defined above:

(output
   (nrotate copy start index) ;
   (recurse (1+ start))
   (nrotate copy start index))

Note that the variable 'copy' in both 'nrotate's are the same when output  
because
you are displaying the call values before evaluating the calls.
It thus only works is the functions have no side effects.
I should write:

(output (nrotate copy start index))
(recurse (1+ start))
(output (nrotate copy start index))

-- 
Using Opera's revolutionary e-mail client: http://www.opera.com/mail/
From: John Thingstad
Subject: Re: combinations not working
Date: 
Message-ID: <op.tli38dt7pqzri1@pandora.upc.no>
On Sun, 31 Dec 2006 17:41:20 +0100, John Thingstad  
<··············@chello.no> wrote:

Just a final thanks to Pascal Bourguignon and nallen05.
The code turned out great! It is agood model for future work.


(defparameter *trace-p* nil)

(defun write-trace (body)
   (when *trace-p*
     (format *trace-output* "~{~&~A~}" body)))

(defun prepare-form (sexp)
   (if (listp sexp)
       `(list ',(prepare-form (first sexp))
	     ,@(mapcar #'prepare-form (rest sexp)))
       sexp))

(defmacro output (&body body)
   `(progn
     (write-trace ,`(list ,@(mapcar #'prepare-form body)))
     ,@body))

(defun fact (n)
   "Compute n! = n * (n-1) * ... * 1"
   (check-type n (integer 0 *))
   (if (member n '(0 1)) 1
       (loop for i from n downto 2
             for p = i then (* p i)
             finally return p)))

(defun count-combinations (sequence)
   "Compute the number of combinations on 'sequence'.
'sequence' can be either a vector or list"
   (check-type sequence (or simple-vector cons))
   (fact (length sequence)))

(defun nrotate (vector start end)
   (rotatef (svref vector start) (svref vector end)))

(defun forall-combinations (vector function)
   "Compute the combinations on 'vector' and call 'function'
on each combination. 'function' is assumed to be a function that
takes a vector argument and does not modify this.
Note that the vector argument given to 'function' is volatile and must be  
copied
if it is stored."
   (check-type vector simple-vector)
   (check-type function function)
   (let ((last (1- (length vector)))
         (copy (copy-seq vector)))
     (labels ((recurse (start)
                (if (= start last)
                    (funcall function copy)
                  (loop for index from start to last do
                        (nrotate copy start index)
                        (recurse (1+ start))
                        (nrotate copy start index)))))
       (recurse 0)))
   (values))

(defun list->vector (list)
   (make-array (length list) :initial-contents list))

(defun vector->list (vector)
   (loop for element across vector collect element))

(defun print-combinations (sequence)
   "Output the combinations a line at a time to standard output.
'sequence' can be either a list or vector.
If 'sequence' is a vector prints as #(...), if it is a list (..)
ex. (print-combinations '(1 2)) prints
   1: (1 2)
   2: (2 1)"
   (check-type sequence (or simple-vector cons))
   (let ((count 0)
         (vector (if (listp sequence) (list->vector sequence) sequence))
         (seq-op (if (listp sequence) #'vector->list #'identity)))
     (flet ((display (vector)
              (incf count)
              (format t "~&~3d: ~A~%" count (funcall seq-op vector))))
       (forall-combinations vector #'display))))

(defun collect-combinations (sequence)
   "Returns a list of the combinations of sequence.
'sequence' can be either a list or a vector.
If 'sequence' is a list returns list of list's otherwise a list of vectors.
ex. (collect-combinations '(1 2)) returns
((1 2) (2 1))"
   (check-type sequence (or simple-vector cons))
   (let ((list nil)
         (vector (if (listp sequence) (list->vector sequence) sequence))
         (seq-op (if (listp sequence) #'vector->list #'copy-seq)))
     (flet ((collect (vector)
              (push (funcall seq-op vector) list)))
       (forall-combinations vector #'collect))
     (nreverse list)))


-- 
Using Opera's revolutionary e-mail client: http://www.opera.com/mail/
From: Bernd Beuster
Subject: Re: combinations not working
Date: 
Message-ID: <engqml$lbs$1@online.de>
John Thingstad schrieb:

> (defun fact (n)
>   "Compute n! = n * (n-1) * ... * 1"
>   (check-type n (integer 0 *))
>   (if (member n '(0 1)) 1
>       (loop for i from n downto 2
>             for p = i then (* p i)
>             finally return p)))

Because declarations are asserts this will help the compiler to optimize
the code:

(defun fact (n)
  "Compute n! = n * (n-1) * ... * 1"
  (declare (type (integer 0 *) n))
  (if (member n '(0 1)) 1
      (loop for i from n downto 2
            for p = i then (* p i)
            finally (return p))))



Or even better:

(defun fact (n)
  "Compute n! = n * (n-1) * ... * 1"
  (declare (fixnum n))
  (if (member n '(0 1)) 1
      (loop for i from n downto 2
            for p = i then (* p i)
            finally (return p))))



-- 
Bernd
From: John Thingstad
Subject: Re: combinations not working
Date: 
Message-ID: <op.tllij60ppqzri1@pandora.upc.no>
On Wed, 03 Jan 2007 18:55:33 +0100, Bernd Beuster <·············@lycos.de>  
wrote:

> Or even better:
>
> (defun fact (n)
>   "Compute n! = n * (n-1) * ... * 1"
>   (declare (fixnum n))
>   (if (member n '(0 1)) 1
>       (loop for i from n downto 2
>             for p = i then (* p i)
>             finally (return p))))
>
>
>

Sounds good until you consider that combinations only will work for 12  
element's or
less. So efficiency is not a problem. Fixnum allows negative integers  
which are not
well defined. I tried various declarations when evaluating this code and  
dropped them
as I found that I cluttered the code and didn't provide any significant  
speed increase.
Anyhow you have to declare i and p fixnum as well (for i as fixnum..)
A better option would be (declaim (inline nrotate)). In ACL it does  
nothing but
in other compilers it would.

-- 
Using Opera's revolutionary e-mail client: http://www.opera.com/mail/
From: John Thingstad
Subject: Re: combinations not working
Date: 
Message-ID: <op.tllkhrr1pqzri1@pandora.upc.no>
On Wed, 03 Jan 2007 21:44:20 +0100, John Thingstad  
<··············@chello.no> wrote:

>
> Sounds good until you consider that combinations only will work for 12  
> element's or
> less. So efficiency is not a problem. Fixnum allows negative integers  
> which are not
> well defined. I tried various declarations when evaluating this code and  
> dropped them
> as I found that I cluttered the code and didn't provide any significant  
> speed increase.
> Anyhow you have to declare i and p fixnum as well (for i as fixnum..)
> A better option would be (declaim (inline nrotate)). In ACL it does  
> nothing but
> in other compilers it would.
>

Incidentally.. (finally (return p)) does't work under LispWorks.
You need either 'finally return p' or 'finally (return-from fact p)'.
So much for portable ;)

-- 
Using Opera's revolutionary e-mail client: http://www.opera.com/mail/
From: Bill Atkins
Subject: Re: combinations not working
Date: 
Message-ID: <not-a-real-email-7A2EBF.17342303012007@host86-26-113-128.not-set-yet.ntli.net>
In article <·················@pandora.upc.no>,
 "John Thingstad" <··············@chello.no> wrote:

> Incidentally.. (finally (return p)) does't work under LispWorks.
> You need either 'finally return p' or 'finally (return-from fact p)'.
> So much for portable ;)

You must be using a different LispWorks than the rest of the world:

CL-USER 1 > (loop for x from 1 to 10
                  finally (return x))
11

CL-USER 2 > (defun test ()
              (loop for x from 1 to 10
                    finally (return x)))
TEST

CL-USER 3 > (test)
11
From: John Thingstad
Subject: Re: combinations not working
Date: 
Message-ID: <op.tlmz4iw8pqzri1@pandora.upc.no>
On Wed, 03 Jan 2007 23:34:30 +0100, Bill Atkins  
<················@not-a-real-domain.com> wrote:

> In article <·················@pandora.upc.no>,
>  "John Thingstad" <··············@chello.no> wrote:
>
>> Incidentally.. (finally (return p)) does't work under LispWorks.
>> You need either 'finally return p' or 'finally (return-from fact p)'.
>> So much for portable ;)
>
> You must be using a different LispWorks than the rest of the world:
>
> CL-USER 1 > (loop for x from 1 to 10
>                   finally (return x))
> 11
>
> CL-USER 2 > (defun test ()
>               (loop for x from 1 to 10
>                     finally (return x)))
> TEST
>
> CL-USER 3 > (test)
> 11

I stand corrected. It works fine in 'fact' so I changed the code.
I have had problems with it earlier as LispWorks likes to put a
(block nil ..) around the macroexpansion which apperently
confused it.

-- 
Using Opera's revolutionary e-mail client: http://www.opera.com/mail/