;; Simulate the same board as one rendered in transient version.
(defn make-special-board [w h]
(let [mid (/ w 2)]
(for [x (range w)]
(for [y (range h)]
[(if (and (= y 0) (<= mid x (inc mid))) :on :off) x y]))))
(defn make-random-board [w h]
(for [x (range w)]
(for [y (range h)]
[(if (< 50 (rand-int 100)) :on :off) x y])))
(defn active-neighbors [above [left _ right] below]
(count
(filter #(= :on (% 0))
(concat above [left right] below))))
(defn torus-window [coll]
(partition 3 1 (concat [(last coll)] coll [(first coll)])))
(defn rules [above current below]
(let [[self x y] (second current)]
(cond
(= :on self) [:dying x y]
(= :dying self) [:off x y]
(= 2 (active-neighbors above current below)) [:on x y]
:else [:off x y])))
(defn step [board f]
(doall
(f (fn [window]
(apply #(doall (apply map rules %&))
(doall (map torus-window window))))
(torus-window board))))
(defn activity-loop [surface stage]
(while true
(swap! stage step)
(.repaint surface)))
(defn simulate [steps initial f]
(loop [n steps, brain initial]
(if (< 0 n)
(recur (dec n) (step brain f))
brain)))
(defn benchmark []
;; Warmup
(simulate 7500 (make-special-board 16 16) map)
(simulate 7500 (make-special-board 16 16) pmap)
(println (clojure-version))
(doseq [[w h i] [[32 32 32768]
[64 64 8192]
[128 128 2048]
[256 256 512]
[512 512 128]]]
(let [initial (doall (make-special-board w h))]
(print (str "S " w "x" h ", " i " iteration(s): "))
(time (simulate i initial map))
(flush)
(print (str "P " w "x" h ", " i " iteration(s): "))
(time (simulate i initial pmap))
(flush))))