Commit 64a631d9 authored by Nikodemus Siivola's avatar Nikodemus Siivola
Browse files

better SHUFFLE

 * Thanks to Sean Ross: implement the Fisher/Yates/Knuth algorithm
   correctly.

 * As penance, specialize for lists as well: travel along the list,
   swapping towards the end -- marginally more efficient then swapping
   along the whole length.
parent 76e78e79
......@@ -51,12 +51,25 @@ result sequence may share structure with it."
(defun shuffle (sequence &key (start 0) end)
"Returns a random permutation of SEQUENCE bounded by START and END.
Permuted sequence may share storage with the original one. Signals
an error if SEQUENCE is not a proper sequence."
Permuted sequence may share storage with the original one. Signals an
error if SEQUENCE is not a proper sequence."
(declare (fixnum start) (type (or fixnum null) end))
(let ((end (or end (if (listp sequence) (list-length sequence) (length sequence)))))
(loop for i from start below end
do (rotatef (elt sequence i) (elt sequence (random end)))))
(typecase sequence
(list
(let* ((end (or end (list-length sequence)))
(n (- end start)))
(do ((tail (nthcdr start sequence) (cdr tail)))
((zerop n))
(rotatef (car tail) (car (nthcdr (random n) tail)))
(decf n))))
(vector
(let ((end (or end (length sequence))))
(loop for i from (- end 1) downto start
do (rotatef (aref sequence i) (aref sequence (random (+ i 1)))))))
(sequence
(let ((end (or end (length sequence))))
(loop for i from (- end 1) downto start
do (rotatef (elt sequence i) (elt sequence (random (+ i 1))))))))
sequence)
(defun random-elt (sequence &key (start 0) end)
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment