<p>
<font face="ARIAL">I asked for the best way to shuffle a list on comp.lang.scheme a few years ago.  The discussion went wild; you can see it on Google Groups if you want.  After that, I wrote this summary:<br></font></p>
<p><font face="ARIAL">It is easy to shuffle a vector by stepping through the vector, swapping each
element with a forward element (including possibly the element itself) until
the next-to-last element is reached.  The classic description is given by
Knuth in AoCP, Volume 2, Section 3.4.2, Algorithm P:
</font></p>
<p><font face="ARIAL"><font face="COURIER"><pre>(define (shuffle v)<br>  (do ((n (length x) (- n 1))) ((zero? n) v))<br>    (let* ((r (random n)) (t (vector-ref v r)))<br>      (vector-set! v r (vector-ref v (- n 1)))<br>
      (vector-set! v (- n 1) t))))<br></pre></font></font></p>
<p>
<font face="ARIAL"><font face="ARIAL">But shuffling a list is harder, because lists don&#39;t permit O(1) access to any
element except the first.  Joe Marshall provides this method of shuffling a
list by partitioning it into two pieces deterministically, shuffling them
recursively, then merging them randomly:
</font></font></p>
<p><font face="ARIAL"><font face="ARIAL"><font face="COURIER"><pre>(define (shuffle xs)<br>  (if (or (null? xs) (null? (cdr xs))) xs<br>      (let split ((xs xs) (odd &#39;()) (even &#39;()))<br>        (if (pair? xs)<br>
            (split (cdr xs) (cons (car xs) even) odd)<br>            (let merge ((odd (shuffle odd)) (even (shuffle even)))<br>              (cond ((null? odd) even)<br>                    ((null? even) odd)<br>                    ((zero? (random 2)) (cons (car odd) (merge (cdr odd) even)))<br>
                    (else (cons (car even) (merge odd (cdr even))))))))))<br></pre></font></font></font></p>
<p>
<font face="ARIAL"><font face="ARIAL"><font face="ARIAL">Al Petrofsky proposes this somewhat faster code that first partitions the list
randomly, then randomly merges them:
</font></font></font></p>
<p><font face="ARIAL"><font face="ARIAL"><font face="ARIAL"><font face="COURIER"><pre>(define (shuffle xs)<br>  (let shuffle ((xs xs) (acc &#39;()))<br>    (if (null? xs) acc<br>        (if (null? (cdr xs)) (cons (car xs) acc)<br>
            (let split ((xs xs) (x1 &#39;()) (x2 &#39;()))<br>              (if (null? xs)<br>                  (if (null? x1)<br>                      (split x2 &#39;() &#39;())<br>                      (shuffle x1 (shuffle x2 acc)))<br>
                  (if (zero? (random 2))<br>                      (split (cdr xs) (cons (car xs) x1) x2)<br>                      (split (cdr xs) x1 (cons (car xs) x2)))))))))<br></pre></font></font></font></font></p>
<p>
<font face="ARIAL"><font face="ARIAL"><font face="ARIAL"><font face="ARIAL">If you want, you can always do Perl&#39;s omigod Schwartzian transform:
</font></font></font></font></p>
<p><font face="ARIAL"><font face="ARIAL"><font face="ARIAL"><font face="ARIAL"><font face="COURIER"><pre>(define (shuffle xs)<br>  (map cdr<br>    (sort (lambda (x y) (&lt; (car x) (car y)))<br>      (map (lambda (x) (cons (random 1.0) x)) xs))))<br>
</pre></font></font></font></font></font></p>
<p>
<font face="ARIAL"><font face="ARIAL"><font face="ARIAL"><font face="ARIAL"><font face="ARIAL">But the fastest method of shuffling a list is to convert it to a vector, use
Knuth&#39;s algorithm to shuffle the vector, then convert it back to a list; this
algorithm operates in linear time (all the others are n log n), and is very
fast despite the two type conversions:
</font></font></font></font></font></p>
<font face="ARIAL"><font face="ARIAL"><font face="ARIAL"><font face="ARIAL"><font face="ARIAL"><font face="COURIER"><pre>(define (shuffle x)<br>  (do ((v (list-&gt;vector x)) (n (length x) (- n 1)))<br>      ((zero? n) (vector-&gt;list v))<br>
    (let* ((r (random n)) (t (vector-ref v r)))<br>      (vector-set! v r (vector-ref v (- n 1)))<br>      (vector-set! v (- n 1) t))))<br></pre></font></font></font></font></font></font><br><br><div class="gmail_quote">On Sun, Aug 9, 2009 at 12:39 PM, Jon Rafkind <span dir="ltr">&lt;<a href="mailto:rafkind@cs.utah.edu">rafkind@cs.utah.edu</a>&gt;</span> wrote:<br>
<blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;"><div class="im">Amit Saha wrote:<br>
<blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
Hello all,<br>
<br>
Here is my Scheme implementation of the &quot;modern&quot; version of the &quot;Fisher Yates Shuffle&quot; (<a href="http://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle" target="_blank">http://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle</a>). I am sharing this with the hope that it may be useful to someone in the community.<br>

<br>
&lt;code&gt;<br>
#lang scheme<br>
<br>
;; Fisher-Yates shuffling algorithm in Scheme (plt-scheme)<br>
;; Amit Saha (<a href="http://amitksaha.wordpress.com" target="_blank">http://amitksaha.wordpress.com</a>; <a href="http://amitsaha.in" target="_blank">amitsaha.in</a>@<a href="http://gmail.com" target="_blank">gmail.com</a>)<br>

<br>
;; Useful to obtain a random shuffle of a list<br>
;; call with (shuffle &lt;your list&gt;)<br>
<br>
(define (shuffle deck)<br>
   (let loop ((n (length deck)) (shuff_deck (list-&gt;vector deck)))<br>
     (if (&lt;= n 1)<br>
       shuff_deck<br>
       (begin<br>
     (set! n (- n 1))<br>
     (let* ([rand (random (+ 1 n))]<br>
           [tmp (vector-ref shuff_deck rand)]<br>
          )<br>
       (vector-set! shuff_deck rand (vector-ref shuff_deck n))<br>
       (vector-set! shuff_deck n tmp))<br>
       (loop n shuff_deck)))))<br>
&lt;/code&gt;<br>
<br>
</blockquote></div>
Heres the one I wrote a while ago<br>
(define (randomize lst)<br>
 (let ((v (list-&gt;vector lst)))<br>
   (let loop ((max (sub1 (vector-length v))))<br>
     (if (= 0 max)<br>
       (vector-&gt;list v)<br>
       (begin<br>
         (let ((place (random max)))<br>
           (let ((tmp (vector-ref v place)))<br>
             (vector-set! v place (vector-ref v max))<br>
             (vector-set! v max tmp)))<br>
         (loop (sub1 max)))))))<br>
<br>
Notable differences are I don&#39;t set! the index variable, nor do I pass along the vector in the loop. Otherwise I guess they are about the same.<div><div></div><div class="h5"><br>
_________________________________________________<br>
 For list-related administrative tasks:<br>
 <a href="http://list.cs.brown.edu/mailman/listinfo/plt-scheme" target="_blank">http://list.cs.brown.edu/mailman/listinfo/plt-scheme</a><br>
</div></div></blockquote></div><br>