Skip to content

Instantly share code, notes, and snippets.

@cgrand
Created November 18, 2009 10:06
Show Gist options
  • Save cgrand/237700 to your computer and use it in GitHub Desktop.
Save cgrand/237700 to your computer and use it in GitHub Desktop.
;; http://clj-me.cgrand.net/2009/11/18/an-optimization-is-never-done/
(import '(javax.swing JFrame JPanel)
'(java.awt Color Graphics2D))
(defn neighbours-count [above current below i w]
(let [j (mod (inc i) w)
k (mod (dec i) w)
s #(if (= (aget #^objects %1 (int %2)) :on) 1 0)]
(+ (+ (+ (s above j) (s above i))
(+ (s above k) (s current j)))
(+ (+ (s current k) (s below j))
(+ (s below i) (s below k))))))
(defn step1 [[above #^objects current below]]
(let [w (count current)]
(loop [i (int (dec w)), #^objects row (aclone current)]
(if (neg? i)
row
(let [c (aget current i)]
(cond
(= c :on)
(recur (dec i) (doto row (aset i :dying)))
(= c :dying)
(recur (dec i) (doto row (aset i :off)))
(= 2 (neighbours-count above current below i w))
(recur (dec i) (doto row (aset i :on)))
:else
(recur (dec i) row)))))))
(defn step [board]
(let [n (.availableProcessors (Runtime/getRuntime))
l (count board)
bounds (map int (range 0 (inc l) (/ l n)))]
(apply into
(pmap #(vec (map step1 (partition 3 1
(concat [(board (mod (dec %1) l))]
(subvec board %1 %2)
[(board (mod %2 l))]))))
bounds (rest bounds)))))
;; utilities and frontend
(defn rand-board [w h]
(vec (map #(into-array Object %) (partition w (take (* w h) (repeatedly #(if (zero? (rand-int 3)) :on :off)))))))
(defn dims [[row :as board]] [(count row) (count board)])
(defn render-board [board #^Graphics2D g cell-size]
(let [[w h] (dims board)]
(doto g
(.setColor Color/BLACK)
(.scale cell-size cell-size)
(.fillRect 0 0 w h))
(doseq [i (range h) j (range w)]
(when-let [color ({:on Color/WHITE :dying Color/GRAY} (aget #^objects (board i) (int j)))]
(doto g
(.setColor color)
(.fillRect j i 1 1))))))
(defn start-brian [board cell-size]
(let [[w h] (dims board)
switch (atom true)
board (atom board)
panel (doto (proxy [JPanel] []
(paint [g] (render-board @board g cell-size)))
(.setDoubleBuffered true))]
(doto (JFrame.)
(.addWindowListener (proxy [java.awt.event.WindowAdapter] []
(windowClosing [_] (reset! switch false))))
(.setSize (* w cell-size) (* h cell-size))
(.add panel)
.show)
(future (while @switch (swap! board step)))
(future (while @switch (.repaint panel) (Thread/sleep 40)))))
(start-brian (rand-board 200 200) 2)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment