(ns example-one.core)
(def suits [:hearts :spades :clubs :diamonds])
(def ranks [:2 :3 :4 :5 :6 :7 :8 :9 :10 :jack :queen :king :ace])
(def deck (vec (for [s suits, r ranks] [s r])))
(set! *warn-on-reflection* true)
(defprotocol ImmutableRandomNumberGenerator
(next-long [self])
(next-state [self]))
(defrecord LaggedFibonacciGenerator [
^long low-backref
^long high-backref
^long current-index
^longs state
]
ImmutableRandomNumberGenerator
(next-long ^long [self]
(aget ^longs (:state self) (:current-index self)))
(next-state ^LaggedFibonacciGenerator [self]
(let [next-index (inc (:current-index self))
low-backref (:low-backref self)
high-backref (:high-backref self)
low-index (mod (- next-index low-backref) high-backref)
high-index (mod (- next-index high-backref) high-backref)
old-state (:state self)
low-value (aget old-state low-index)
high-value (aget old-state high-index)
new-state (aclone old-state)]
(aset-long new-state next-index (unchecked-add ^long low-value ^long high-value))
(LaggedFibonacciGenerator. low-backref high-backref next-index new-state))))
(defn- make-rng ^LaggedFibonacciGenerator []
(let [seed-prng (java.security.SecureRandom.)
init-state (long-array (repeatedly 55 #(.nextLong seed-prng)))]
(LaggedFibonacciGenerator. 24 55 0 init-state)))
(defn shuffle-deck
"Creates a shuffled deck of cards"
[]
(loop [deck (transient deck), i (dec (count deck)), rng (make-rng)]
(if (zero? i)
(persistent! deck)
(let [j (mod (next-long rng) i)]
(recur (assoc! deck i (deck j) j (deck i))
(dec i)
(next-state rng))))))
(let [shuffled (shuffle-deck)]
(println (count shuffled))
(println shuffled))