Skip to content

Instantly share code, notes, and snippets.

@drocamor
Created June 24, 2012 20:09
Show Gist options
  • Save drocamor/2984718 to your computer and use it in GitHub Desktop.
Save drocamor/2984718 to your computer and use it in GitHub Desktop.
Clojure deck shuffling
(ns shuffler.core)
(defn shuffle-a-deck []
"""Shuffles one deck of cards"""
(clojure.string/join "," (shuffle (range 0 52))))
;; this is an infinite number of shuffled decks of cards
(def shuffled-decks (repeatedly shuffle-a-deck))
(defn find-a-dup [seq index]
"""Finds the first duplicate in a seq"""
(cond
;; Return the index if we find the indexed item in the first part of the seq
(some #{(nth seq index)} (take index seq)) index
;; Otherwise, return a function to keep going
:else #(find-a-dup seq (+ 1 index))))
;; You can run this at the REPL like so:
;;
;; (time (trampoline fund-a-dup shuffled-decks 0))
;;
;; Originally I wrote this as a recursive function, but too much recursion causes a stack overflow.
;; trampoline elimates this issue.
;;
;; It will time itself while it flips through the seq looking for the first duplicate.
;;
;; I can find a duplicate in a 10 card deck after about 3000-5000 decks.
;; I think that with 52 cards we run out a memory well before we can find an answer.
;;
;; There is probably a better way to do this. This gets slower and slower as it realizes more and more of the seq.
;; Can you do this without having to evaluate every deck that has come before?
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment