Skip to content

Instantly share code, notes, and snippets.

@shortsightedsid
Last active February 18, 2020 12:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save shortsightedsid/62d0ee21bfca53d9b69e to your computer and use it in GitHub Desktop.
Save shortsightedsid/62d0ee21bfca53d9b69e to your computer and use it in GitHub Desktop.
Shuffle a list
;; Easy Daily Programmer https://www.reddit.com/r/dailyprogrammer/comments/3e0hmh/20150720_challenge_224_easy_shuffling_a_list/
(defun list-shuffler-recursive (input-list &optional accumulator)
"Shuffle a list using tail call recursion."
(if (eq input-list nil)
accumulator
(progn
(rotatef (car input-list)
(nth (random (length input-list)) input-list))
(list-shuffler-recursive (cdr input-list)
(append accumulator (list (car input-list)))))))
(defun list-shuffler-iterative (input-list)
"Shuffle a list iteratively using a loop"
(loop with l = (length input-list)
for i below l
do (rotatef (nth i input-list)
(nth (random l) input-list)))
input-list)
(defun array-shuffler-iterative (input-array)
"Shuffle a array iteratively using a loop"
(loop with l = (length input-array)
for i below l
do (rotatef (aref input-array i)
(aref input-array (random l))))
input-array)
;; The array based version is atleast 4 times faster than using lists. Both iterative versions do not cons any bytes in SBCL
@cpaulbond
Copy link

I saw this someplace years ago, and I always laugh when I think about shuffling and this algorithm.

;; Fast way to shuffle?
(let ((a (list 1 2 3 4 5 6 7 8 9)))
  (setf a (sort a (lambda (a b) (declare (ignorable a b)) (= 1 (random 2)))))
  (format t "~a~%" a))

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment