<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:georss="http://www.georss.org/georss" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:media="http://search.yahoo.com/mrss/"
		>
<channel>
	<title>Comments on: Shuffle</title>
	<atom:link href="http://programmingpraxis.com/2009/10/20/shuffle/feed/" rel="self" type="application/rss+xml" />
	<link>http://programmingpraxis.com/2009/10/20/shuffle/</link>
	<description>A collection of etudes, updated weekly, for the education and enjoyment of the savvy programmer</description>
	<lastBuildDate>Mon, 28 May 2012 03:30:45 +0000</lastBuildDate>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.com/</generator>
	<item>
		<title>By: Vikas Tandi</title>
		<link>http://programmingpraxis.com/2009/10/20/shuffle/#comment-2988</link>
		<dc:creator><![CDATA[Vikas Tandi]]></dc:creator>
		<pubDate>Fri, 06 May 2011 04:31:11 +0000</pubDate>
		<guid isPermaLink="false">http://programmingpraxis.com/?p=1549#comment-2988</guid>
		<description><![CDATA[MY c IMPLEMENTATION
[sourcecode lang=&quot;cpp&quot;]
#include &lt;stdlib.h&gt;
#include &lt;time.h&gt;

static void swap(int arr[], int i, int j);

void shuffle_array(int arr[], int n)
{
	int i, j;

	srand((unsigned int)time(NULL));

	for(j = n; j &gt; 1; j--)
	{
		i = (rand() % j) + 1;
		swap(arr, i-1, j-1);
	}
}

void shuffle_linklist(List **p)
{
	List *ptr, *currentp, *newp;
	int size, randnum;

	if(*p == NULL)
		return;

	/* calculate Linklist size */
	for(size = 0, currentp = *p; currentp != NULL; size++, currentp = currentp-&gt;next);

	/* shuffle */

	/* Shuffle single node */
	srand((unsigned int)time(NULL));
	randnum = (rand() % size) + 1;
	ptr = *p;
	currentp = *p;

	while(--randnum &gt; 1)
		currentp = currentp-&gt;next;

	/* first node */
	if(currentp == ptr)
	{
		ptr = ptr-&gt;next;
		*p = currentp;
	}
	else
	{
		*p = currentp-&gt;next;
		currentp-&gt;next = currentp-&gt;next-&gt;next;
	}
	(*p)-&gt;next;

	if(size == 1)
		return;

	/* shuffle remaining node */
	for(size = size-1, currentp = ptr, newp = *p; size &gt; 1; currentp = ptr, size--, newp = newp-&gt;next)
	{
		randnum = (rand() % size) + 1;
		while(--randnum &gt; 1)
			currentp = currentp-&gt;next;

		/* first node */
		if(currentp == ptr)
		{
			ptr = ptr-&gt;next;
			newp-&gt;next = currentp;
		}
		else
		{
			newp-&gt;next = currentp-&gt;next;
			currentp-&gt;next = currentp-&gt;next-&gt;next;
		}
		newp-&gt;next-&gt;next = NULL;
	}

	/* add last node */
	newp-&gt;next = ptr;
	newp-&gt;next-&gt;next = NULL;
}

static void swap(int arr[], int i, int j)
{
	int tmp;

	tmp = arr[i];
	arr[i] = arr[j];
	arr[j] = tmp;
}
[/sourcecode]]]></description>
		<content:encoded><![CDATA[<p>MY c IMPLEMENTATION</p>
<pre class="brush: cpp;">
#include &lt;stdlib.h&gt;
#include &lt;time.h&gt;

static void swap(int arr[], int i, int j);

void shuffle_array(int arr[], int n)
{
	int i, j;

	srand((unsigned int)time(NULL));

	for(j = n; j &gt; 1; j--)
	{
		i = (rand() % j) + 1;
		swap(arr, i-1, j-1);
	}
}

void shuffle_linklist(List **p)
{
	List *ptr, *currentp, *newp;
	int size, randnum;

	if(*p == NULL)
		return;

	/* calculate Linklist size */
	for(size = 0, currentp = *p; currentp != NULL; size++, currentp = currentp-&gt;next);

	/* shuffle */

	/* Shuffle single node */
	srand((unsigned int)time(NULL));
	randnum = (rand() % size) + 1;
	ptr = *p;
	currentp = *p;

	while(--randnum &gt; 1)
		currentp = currentp-&gt;next;

	/* first node */
	if(currentp == ptr)
	{
		ptr = ptr-&gt;next;
		*p = currentp;
	}
	else
	{
		*p = currentp-&gt;next;
		currentp-&gt;next = currentp-&gt;next-&gt;next;
	}
	(*p)-&gt;next;

	if(size == 1)
		return;

	/* shuffle remaining node */
	for(size = size-1, currentp = ptr, newp = *p; size &gt; 1; currentp = ptr, size--, newp = newp-&gt;next)
	{
		randnum = (rand() % size) + 1;
		while(--randnum &gt; 1)
			currentp = currentp-&gt;next;

		/* first node */
		if(currentp == ptr)
		{
			ptr = ptr-&gt;next;
			newp-&gt;next = currentp;
		}
		else
		{
			newp-&gt;next = currentp-&gt;next;
			currentp-&gt;next = currentp-&gt;next-&gt;next;
		}
		newp-&gt;next-&gt;next = NULL;
	}

	/* add last node */
	newp-&gt;next = ptr;
	newp-&gt;next-&gt;next = NULL;
}

static void swap(int arr[], int i, int j)
{
	int tmp;

	tmp = arr[i];
	arr[i] = arr[j];
	arr[j] = tmp;
}
</pre>
]]></content:encoded>
	</item>
	<item>
		<title>By: programmingpraxis</title>
		<link>http://programmingpraxis.com/2009/10/20/shuffle/#comment-1772</link>
		<dc:creator><![CDATA[programmingpraxis]]></dc:creator>
		<pubDate>Mon, 11 Oct 2010 14:10:32 +0000</pubDate>
		<guid isPermaLink="false">http://programmingpraxis.com/?p=1549#comment-1772</guid>
		<description><![CDATA[I haven&#039;t looked closely, but isn&#039;t your algorithm O(n log n), like any other divide-and-conquer algorithm?  The advantage of the list-&gt;vector-&gt;knuth-shuffle-&gt;list algorithm is that it works in O(n) time. ]]></description>
		<content:encoded><![CDATA[<p>I haven&#8217;t looked closely, but isn&#8217;t your algorithm O(n log n), like any other divide-and-conquer algorithm?  The advantage of the list-&gt;vector-&gt;knuth-shuffle-&gt;list algorithm is that it works in O(n) time. </p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Ben Goldberg</title>
		<link>http://programmingpraxis.com/2009/10/20/shuffle/#comment-1771</link>
		<dc:creator><![CDATA[Ben Goldberg]]></dc:creator>
		<pubDate>Sun, 10 Oct 2010 17:33:37 +0000</pubDate>
		<guid isPermaLink="false">http://programmingpraxis.com/?p=1549#comment-1771</guid>
		<description><![CDATA[To shuffle a linked list without converting it into an array or treating it as if it were an array, create two temporary lists, left and right, and then for each element in the original list, move that element randomly into either left or right.  Then use recursion shuffle each of the left and right lists, combine them, and return the combined list.

Of course, doing two recursive calls can result in lots of memory usage, especially since the random selection could potentially put all elements of the original into left, or all into right... which adds to the stack depth, while accomplishing little work.

Instead, after partitioning into left and right, join the lists back together &lt;B&gt;before&lt;/B&gt; shuffling, so that one of the two recursive calls can be changed into a loop.

Here&#039;s some lisp code to do it:

[sourcecode lang=&quot;css&quot;]
(defun partition (before exclude)
  &quot;Destructively randomly partition part of a list (starting with
(rest BEFORE), up to, but not including, EXCLUDE) into two lists,
which (concatenated together) are then inserted into the original
list in their original place.&quot;
  ;(format t &quot;Partition ~A ~A~%&quot; before exclude)
  (do (lft rgt lend rend llen rlen)
      ((and lend rend)
       (setf (rest before) lft (rest lend) rgt (rest rend) exclude)
       (values rgt (&lt; llen rlen)))
    ;(format t &quot;partition, looping~%&quot;)
    (setf lft nil lend nil rgt nil rend nil llen 0 rlen 0)
    (do ((y (rest before) (rest y))) ((eq y exclude))
      ; move each cons onto the end of either the left or
      ; right list, keeping track of where the list ends are.
      (if (zerop (random 2))
          (and (incf llen) (if (not lft)
                               (setf lft y lend y)
                               (setf (rest lend) y lend y)))
          (and (incf rlen) (if (not rgt)
                               (setf rgt y rend y)
                               (setf (rest rend) y rend y)))))))

(defun shuf-internal (before exclude)
  &quot;Destructively shuffles the list which starts with (rest BEFORE), up to and excluding
the cons EXCLUDE.  Returns nothing.&quot;
  ;(format t &quot;shuf-internal ~A ~A~%&quot; before exclude)
  ; create a &quot;working&quot; list from mystart to myend, inclusive.
  ; Loop as long as the working list&#039;s length is &gt; 1
  (do ()
      ((or (eq (rest before) exclude) (eq (cddr before) exclude)) (values &#039;foo!))
    ;(format t &quot;m-v-b~%&quot;)
    (multiple-value-bind (rgt rec-left) (partition before exclude)
      ;(format t &quot;After part, before is ~A, rgt is ~A, doleft is ~A~%&quot; before rgt rec-left)
      (if rec-left
          (progn (shuf-internal before rgt) (setf before rgt))
          (progn (shuf-internal rgt exclude) (setf exclude rgt))))))

(defun nshuffle (thelist)
  (let ((dummyhead (cons &#039;dummy-head-value thelist)))
    (shuf-internal dummyhead nil)
    (rest dummyhead)))
[/sourcecode]

Alternatively, here&#039;s some C code:

[sourcecode language=&quot;cpp&quot;]
typedef struct node {
	int data;
	struct node * next;
} node, *list;

static void shl(list *before, node *after);

void shufflelist(list * head) {
	if(head != NULL) shl(head, NULL);
}

#define RANDBOOL() (rand() &gt; (RAND_MAX/2))

static void shl(list *before, node *after) {
	while( *before != after &amp;&amp; (*before)-&gt;next != after ) {
		redo:
		list lft = NULL, rgt = NULL;
		node *lend = NULL, *rend = NULL;
		int llen = 0, rlen = 0;
		for( node *i = *before; i != after; i = i-&gt;next )
			if( RANDBOOL() ) {
				if( lft ) lend-&gt;next = i; else lft = i;
				lend = i;
				++llen;
			} else {
				if( rgt ) rend-&gt;next = i; else rgt = i;
				rend = i;
				++rlen;
			}
		if( !lft &#124;&#124; !rgt ) goto redo;
		*before = lft;
		lend-&gt;next = rgt;
		rend-&gt;next = after;
		if( llen &lt; rlen ) {
			shl(before, rgt);
			before = &amp;(rgt-&gt;next);
		} else {
			shl(rgt, after);
			after = rgt;
		}
	}
}
[/sourcecode]

This would be used as:
[sourcecode lang=&quot;cpp&quot;]
list mylist = NULL;
for( int i = 0; i &lt; 10; ++i )
   insert_front(&amp;mylist, i);
shuffle(&amp;mylist);
[/sourcecode]

PS: I&#039;ve only tested the lisp code, since I&#039;m still working on installing gcc on my computer.
But since the algorithm is the same, they should work the same.]]></description>
		<content:encoded><![CDATA[<p>To shuffle a linked list without converting it into an array or treating it as if it were an array, create two temporary lists, left and right, and then for each element in the original list, move that element randomly into either left or right.  Then use recursion shuffle each of the left and right lists, combine them, and return the combined list.</p>
<p>Of course, doing two recursive calls can result in lots of memory usage, especially since the random selection could potentially put all elements of the original into left, or all into right&#8230; which adds to the stack depth, while accomplishing little work.</p>
<p>Instead, after partitioning into left and right, join the lists back together <b>before</b> shuffling, so that one of the two recursive calls can be changed into a loop.</p>
<p>Here&#8217;s some lisp code to do it:</p>
<pre class="brush: css;">
(defun partition (before exclude)
  &quot;Destructively randomly partition part of a list (starting with
(rest BEFORE), up to, but not including, EXCLUDE) into two lists,
which (concatenated together) are then inserted into the original
list in their original place.&quot;
  ;(format t &quot;Partition ~A ~A~%&quot; before exclude)
  (do (lft rgt lend rend llen rlen)
      ((and lend rend)
       (setf (rest before) lft (rest lend) rgt (rest rend) exclude)
       (values rgt (&lt; llen rlen)))
    ;(format t &quot;partition, looping~%&quot;)
    (setf lft nil lend nil rgt nil rend nil llen 0 rlen 0)
    (do ((y (rest before) (rest y))) ((eq y exclude))
      ; move each cons onto the end of either the left or
      ; right list, keeping track of where the list ends are.
      (if (zerop (random 2))
          (and (incf llen) (if (not lft)
                               (setf lft y lend y)
                               (setf (rest lend) y lend y)))
          (and (incf rlen) (if (not rgt)
                               (setf rgt y rend y)
                               (setf (rest rend) y rend y)))))))

(defun shuf-internal (before exclude)
  &quot;Destructively shuffles the list which starts with (rest BEFORE), up to and excluding
the cons EXCLUDE.  Returns nothing.&quot;
  ;(format t &quot;shuf-internal ~A ~A~%&quot; before exclude)
  ; create a &quot;working&quot; list from mystart to myend, inclusive.
  ; Loop as long as the working list's length is &gt; 1
  (do ()
      ((or (eq (rest before) exclude) (eq (cddr before) exclude)) (values 'foo!))
    ;(format t &quot;m-v-b~%&quot;)
    (multiple-value-bind (rgt rec-left) (partition before exclude)
      ;(format t &quot;After part, before is ~A, rgt is ~A, doleft is ~A~%&quot; before rgt rec-left)
      (if rec-left
          (progn (shuf-internal before rgt) (setf before rgt))
          (progn (shuf-internal rgt exclude) (setf exclude rgt))))))

(defun nshuffle (thelist)
  (let ((dummyhead (cons 'dummy-head-value thelist)))
    (shuf-internal dummyhead nil)
    (rest dummyhead)))
</pre>
<p>Alternatively, here&#8217;s some C code:</p>
<pre class="brush: cpp;">
typedef struct node {
	int data;
	struct node * next;
} node, *list;

static void shl(list *before, node *after);

void shufflelist(list * head) {
	if(head != NULL) shl(head, NULL);
}

#define RANDBOOL() (rand() &gt; (RAND_MAX/2))

static void shl(list *before, node *after) {
	while( *before != after &amp;&amp; (*before)-&gt;next != after ) {
		redo:
		list lft = NULL, rgt = NULL;
		node *lend = NULL, *rend = NULL;
		int llen = 0, rlen = 0;
		for( node *i = *before; i != after; i = i-&gt;next )
			if( RANDBOOL() ) {
				if( lft ) lend-&gt;next = i; else lft = i;
				lend = i;
				++llen;
			} else {
				if( rgt ) rend-&gt;next = i; else rgt = i;
				rend = i;
				++rlen;
			}
		if( !lft || !rgt ) goto redo;
		*before = lft;
		lend-&gt;next = rgt;
		rend-&gt;next = after;
		if( llen &lt; rlen ) {
			shl(before, rgt);
			before = &amp;(rgt-&gt;next);
		} else {
			shl(rgt, after);
			after = rgt;
		}
	}
}
</pre>
<p>This would be used as:</p>
<pre class="brush: cpp;">
list mylist = NULL;
for( int i = 0; i &lt; 10; ++i )
   insert_front(&amp;mylist, i);
shuffle(&amp;mylist);
</pre>
<p>PS: I&#8217;ve only tested the lisp code, since I&#8217;m still working on installing gcc on my computer.<br />
But since the algorithm is the same, they should work the same.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Michel S.</title>
		<link>http://programmingpraxis.com/2009/10/20/shuffle/#comment-728</link>
		<dc:creator><![CDATA[Michel S.]]></dc:creator>
		<pubDate>Tue, 27 Oct 2009 21:54:27 +0000</pubDate>
		<guid isPermaLink="false">http://programmingpraxis.com/?p=1549#comment-728</guid>
		<description><![CDATA[Here is an implementation in Clojure. Its native datatypes are immutable, so for the array shuffle I&#039;m using Java&#039;s ArrayList. The collection shuffler works on any ordered Clojure collection (immutable lists as well as vectors); because values are immutable, we are modifying what the variables point to, which has to be done within a software transaction with dosync.

[sourcecode lang=&quot;css&quot;]
(import &#039;java.util.ArrayList)

(defmulti shuffle type)

(defmethod shuffle ArrayList [#^ArrayList arr]
  (letfn [(swap!
	   [i j]
	   (let [t (.get arr i)]
	     (doto arr
	       (.set i (.get arr j))
	       (.set j t))))]
    (doseq [x (range (dec (.size arr)) -1 -1)]
      (swap! x (rand-int x)))
    arr))

;; alternate shuffler:
;; #(sort (fn [x y] (dec (rand-int 3))) %)

(defmethod shuffle clojure.lang.Ref [coll]
  (letfn [(shuffler
	   [coll]
	   (if (or (empty? coll) (empty? (next coll))) coll
	       (let [c (count coll)
		     pick (rand-int c)]
		 (cons (nth coll pick)
		       (concat (shuffler (take pick coll))
			       (shuffler (drop (inc pick) coll)))))))]
		    
    (dosync (alter coll shuffler))))

[/sourcecode]]]></description>
		<content:encoded><![CDATA[<p>Here is an implementation in Clojure. Its native datatypes are immutable, so for the array shuffle I&#8217;m using Java&#8217;s ArrayList. The collection shuffler works on any ordered Clojure collection (immutable lists as well as vectors); because values are immutable, we are modifying what the variables point to, which has to be done within a software transaction with dosync.</p>
<pre class="brush: css;">
(import 'java.util.ArrayList)

(defmulti shuffle type)

(defmethod shuffle ArrayList [#^ArrayList arr]
  (letfn [(swap!
	   [i j]
	   (let [t (.get arr i)]
	     (doto arr
	       (.set i (.get arr j))
	       (.set j t))))]
    (doseq [x (range (dec (.size arr)) -1 -1)]
      (swap! x (rand-int x)))
    arr))

;; alternate shuffler:
;; #(sort (fn [x y] (dec (rand-int 3))) %)

(defmethod shuffle clojure.lang.Ref [coll]
  (letfn [(shuffler
	   [coll]
	   (if (or (empty? coll) (empty? (next coll))) coll
	       (let [c (count coll)
		     pick (rand-int c)]
		 (cons (nth coll pick)
		       (concat (shuffler (take pick coll))
			       (shuffler (drop (inc pick) coll)))))))]
		    
    (dosync (alter coll shuffler))))

</pre>
]]></content:encoded>
	</item>
	<item>
		<title>By: Ed Siok</title>
		<link>http://programmingpraxis.com/2009/10/20/shuffle/#comment-713</link>
		<dc:creator><![CDATA[Ed Siok]]></dc:creator>
		<pubDate>Thu, 22 Oct 2009 15:21:01 +0000</pubDate>
		<guid isPermaLink="false">http://programmingpraxis.com/?p=1549#comment-713</guid>
		<description><![CDATA[Here&#039;s an example of the array shuffle in perl (without using the pre-existing library). Perl doesn&#039;t generally support linked lists as all arrays have the push/pop/etc functionality included.

&lt;a href=&quot;http://codepad.org/0I2Y1Osz&quot; rel=&quot;nofollow&quot;&gt;Perl array shuffle example&lt;/a&gt;]]></description>
		<content:encoded><![CDATA[<p>Here&#8217;s an example of the array shuffle in perl (without using the pre-existing library). Perl doesn&#8217;t generally support linked lists as all arrays have the push/pop/etc functionality included.</p>
<p><a href="http://codepad.org/0I2Y1Osz" rel="nofollow">Perl array shuffle example</a></p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Sam TH</title>
		<link>http://programmingpraxis.com/2009/10/20/shuffle/#comment-702</link>
		<dc:creator><![CDATA[Sam TH]]></dc:creator>
		<pubDate>Tue, 20 Oct 2009 13:27:38 +0000</pubDate>
		<guid isPermaLink="false">http://programmingpraxis.com/?p=1549#comment-702</guid>
		<description><![CDATA[Here&#039;s a PLT version, which works like the Perl version:

(define (shuffle x) (sort x #:key (lambda _ (random)) #:cache-keys? #t))]]></description>
		<content:encoded><![CDATA[<p>Here&#8217;s a PLT version, which works like the Perl version:</p>
<p>(define (shuffle x) (sort x #:key (lambda _ (random)) #:cache-keys? #t))</p>
]]></content:encoded>
	</item>
</channel>
</rss>

