user=> (use 'clojure.contrib.seq-utils)
nil
user=> (shuffle (list 1 2 3 4))
(3 4 1 2)
-Lee
> --
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to clo...@googlegroups.com
> Note that posts from new members are moderated - please be patient with your first post.
> To unsubscribe from this group, send email to
> clojure+u...@googlegroups.com
> For more options, visit this group at
> http://groups.google.com/group/clojure?hl=en
--
Lee Spector, Professor of Computer Science
School of Cognitive Science, Hampshire College
893 West Street, Amherst, MA 01002-3359
lspe...@hampshire.edu, http://hampshire.edu/lspector/
Phone: 413-559-5352, Fax: 413-559-5438
Check out Genetic Programming and Evolvable Machines:
http://www.springer.com/10710 - http://gpemjournal.blogspot.com/
If you want to do it yourself, the easiest would be
(defn naive-shuffle [xs]
(let [v (vec xs)]
(->> (count v) range lex-permutations rand-elt (map v))))
This uses the seq-utils and combinatorics libraries from clojure.contrib.
However, generating all permutations obviously doesn't scale beyond a
couple of elements. For that you will need a real algorithm like the
Knuth shuffle:
(defn swap-elts [x i j]
(assoc x i (x j) j (x i)))
(defn rand-range
([n] (rand-int n))
([m n] (+ m (rand-int (- n m)))))
(defn knuth-shuffle [xs]
(let [v (vec xs)]
(reduce #(swap-elts %1 %2 (rand-range %2 (count %1))) v (range (count v)))))
-Per
(defn shuffle
[lst]
(if (empty? (rest lst))
lst
(let [index (rand-int (count lst))
item (nth lst index)
remainder (concat (subvec (into [] lst) 0 index)
(subvec (into [] lst) (inc index)))]
(cons item (shuffle remainder)))))
-Lee
> To unsubscribe, reply using "remove me" as the subject.
(defn rand-range [m n]
(+ m (rand-int (- n m))))
(defn swap-entries! [x i j]
(assoc! x i (x j) j (x i)))
(defn knuth-shuffle [xs]
(let [v (transient (vec xs)), n (count v)]
(persistent! (reduce #(swap-entries! %1 %2 (rand-range %2 n)) v
(range n)))))
-Per
-Per
-Lee
Embrace recursion combinators! They are warm and fuzzy!
Here's a gist of the final cleaned up version of my code. The code
itself is only three lines; the rest consists of very general purpose
utilities that I find myself using again and again.
-Per
Also, I'd reverse the arg order of with-transient. I think
(with-transient f x)
reads easier. Also, it should probably end with a bang, because I
don't think it's safe in the STM.
Great work guys.
Sean
On Apr 5, 12:52 am, Per Vognsen <per.vogn...@gmail.com> wrote:
> > lspec...@hampshire.edu,http://hampshire.edu/lspector/
> > Phone: 413-559-5352, Fax: 413-559-5438
>
> > Check out Genetic Programming and Evolvable Machines:
> >http://www.springer.com/10710-http://gpemjournal.blogspot.com/
user> (def v (vec (range 500000)))
#'user/v
user> (time (do (doall (shuffle v)) nil))
"Elapsed time: 449.001 msecs"
nil
user> (def a (java.util.ArrayList. v))
#'user/array
user> (time (do (java.util.Collections/shuffle a) nil))
"Elapsed time: 102.331 msecs"
nil
Each of those timings were repeated several things to make sure they
were sufficiently stable.
The conclusion is that java.util.Collections.shuffle is plenty fast.
Most of the time (over 3/4ths) taken by seq-utils.shuffle goes into
conversions. But even 450 ms for shuffling a 500,000 element list
isn't too bad. For comparison, the time to sum that many elements with
#(reduce + %) is about 50 ms.
-Per