How to generate repeatable random sequences with rand-int

clojure

Solution

Probably not the cleanest way, but you can make it work by redefining `clojure.core/rand`:

(ns clojure.core)

(def r (java.util.Random. 1))

(defn rand
  ([] (.nextDouble r))
  ([n] (.nextInt r n)))

(take 10 (repeatedly #(rand-int 10)))

This produces (5 8 7 3 4 4 4 6 8 8) every time I run it.

Problem

I want to be able to generate repeatable numbers using `rand` in Clojure. (Specifically, I want results of calls to `rand-nth` or Incanter's `sample` to be repeatable, and these call `rand-int` which in turn calls `rand`). I figured out from this question that if I use clojure.data.generators, I can reset the random state: ``` (require '[clojure.data.generators :as gen]) (alter-var-root #'gen/*rnd* (constantly (java.util.Random. 437))) (gen/reservoir-sample 5 (range 1000)) ; => [940 591 636 12 755] (gen/reservoir-sample 5 (range 1000)) ; => [376 540 827 307 463] ; reset random state: (alter-var-root #'gen/*rnd* (constantly (java.util.Random. 437))) ; now the same results are generated again: (gen/reservoir-sample 5 (range 1000)) ; => [940 591 636 12 755] (gen/reservoir-sample 5 (range 1000)) ; => [376 540 827 307 463] ``` However, that method only seems to affect functions in clojure.data.generators, which isn't surprising: ``` (alter-var-root #'gen/*rnd* (constantly (java.util.Random. 437))) (rand) ; => 0.9372552374760151 (rand) ; => 0.2712729314667742 ; reset random state: (alter-var-root #'gen/*rnd* (constantly (java.util.Random. 437))) ; not same results as before: (rand) ; => 0.630238593767316 (rand) ; => 0.426744420572015 ``` How can I restore the random state in such as way as to get repeatable results from `rand`? So far I haven't found any documentation about this. (Another question sounds as if it might be the same issue, but it's asking about something completely different.)

Original source

Related problems