Skip to content

Instantly share code, notes, and snippets.

@simon-brooke
Forked from mowat27/01_game_of_life.clj
Last active August 29, 2015 14:00
Show Gist options
  • Save simon-brooke/ca9821ffd4e12da8ef23 to your computer and use it in GitHub Desktop.
Save simon-brooke/ca9821ffd4e12da8ef23 to your computer and use it in GitHub Desktop.
(ns game-of-life.core)
(def world [[2 1] [2 2] [1 1]])
(defn neighbours [[x y]]
[[(dec x) (dec y)] [x (dec y)] [(inc x) (dec y)]
[(dec x) y] [(inc x) y]
[(dec x) (inc y)] [x (inc y)] [(inc x) (inc y)]])
(neighbours [2 2])
(defn count-live-neighbours [world nbrs]
(count (filter #(>= % 0) (map #(.indexOf world %) nbrs))))
(count-live-neighbours [[2 1] [5 5]] (neighbours [2 2]))
(defn alive? [world coords]
(> (.indexOf world coords) -1))
(defn survives? [world coords]
(let [n (count-live-neighbours world (neighbours coords))]
(cond (and (alive? world coords) (or (= n 2) (= n 3))) true
:else (= n 3))))
(defn min-x [world]
(apply min (map first world)))
(defn max-x [world]
(apply max (map first world)))
(defn min-y [world]
(apply min (map second world)))
(defn max-y [world]
(apply max (map second world)))
(defn xcoords
([world]
(xcoords world (dec (min-x world))))
([world n]
(cond
(= n (inc (max-x world))) (list n)
:else (cons n (xcoords world (inc n))))
))
(defn ycoords
([world]
(ycoords world (dec (min-y world))))
([world n]
(cond
(= n (inc (max-y world))) (list n)
:else (cons n (ycoords world (inc n))))
))
(defn next-gen [world]
(for [x (xcoords world)
y (ycoords world)
:when (survives? world [x y])]
[x y]))
(let [world [[1 2] [2 2] [3 2]]]
(take 5 (iterate next-gen world)))
(ns game-of-life.core)
(def world [[2 1] [2 2] [1 1]])
(defn neighbours [[x y]]
[[(dec x) (dec y)] [x (dec y)] [(inc x) (dec y)]
[(dec x) y] [(inc x) y]
[(dec x) (inc y)] [x (inc y)] [(inc x) (inc y)]])
(neighbours [2 2])
(defn count-live-neighbours [world nbrs]
(count (filter (into #{} world) nbrs)))
(count-live-neighbours [[2 1] [1 1]] (neighbours [2 2]))
(defn alive? [world coords]
(not (nil? (get (into #{} world) coords))))
(defn survives? [world coords]
(let [n (count-live-neighbours world (neighbours coords))]
(cond (and (alive? world coords) (or (= n 2) (= n 3))) true
:else (= n 3))))
(defn min-max [f world]
((juxt #(apply min %) #(apply max %)) (map f world)))
(defn extents [world]
(let [[min-x max-x] (min-max first world)
[min-y max-y] (min-max second world)]
[(range (dec min-x) (+ 2 max-x))
(range (dec min-y) (+ 2 max-y))]))
(defn next-gen [world]
(let [[xs ys] (extents world)]
(for [x xs
y ys
:when (survives? world [x y])]
[x y])))
(def expected [[[1 2] [2 2] [3 2]]
[[2 1] [2 2] [2 3]]
[[1 2] [2 2] [3 2]]
[[2 1] [2 2] [2 3]]
[[1 2] [2 2] [3 2]]])
(def actual
(vec (let [world [[1 2] [2 2] [3 2]]]
(map vec (take 5 (iterate next-gen world))))))
(= expected actual)
(ns life.core
"A game of life, in which a world is represented as a sparse array,
and live cells are represented as a pair of integers x, y.")
(defn neighbours [[x y]]
"Return the pairs of coordinates which are immediate neighbours of this pair."
[[(dec x) (dec y)] [x (dec y)] [(inc x) (dec y)]
[(dec x) y] [(inc x) y]
[(dec x) (inc y)] [x (inc y)] [(inc x) (inc y)]])
(defn alive? [world coords]
"Return true if the cell at these coordinates in this world is alive."
((set world) coords))
(defn count-live-neighbours [world coords]
"Return the number of live neighbours of these coordinates in this world."
(count (remove nil? (map #(alive? world %) (neighbours coords)))))
(defn survives? [world coords]
"Return true if the cell at these coordinates in this world survives to the next generation."
(let [n (count-live-neighbours world coords)]
(or (= n 3) (and (alive? world coords) (= n 2)))))
(defmacro minxymaxy [world fun coord]
"Nasty little macro to write the min and max x and y functions."
(list 'apply fun (list 'map coord world)))
(defn min-x [world]
"Return the minimum X coordinate in this world."
(minxymaxy world min first))
(defn max-x [world]
"Return the maximum X coordinate in this world."
(minxymaxy world max first))
(defn min-y [world]
"Return the minimum Y coordinate in this world."
(minxymaxy world min second))
(defn max-y [world]
"Return the maximum Y coordinate in this world."
(minxymaxy world max second))
(defn xcoords
[world]
"Return the X coordinates which are interesting for this world."
(range (dec (min-x world)) (+ (max-x world) 2)))
(defn ycoords
[world]
"Return the Y coordinates which are interesting for this world."
(range (dec (min-y world)) (+ (max-y world) 2)))
(defn next-gen [world]
"Return the next generation of this world."
(for [x (xcoords world)
y (ycoords world)
:when (survives? world [x y])]
[x y]))
@simon-brooke
Copy link
Author

I haven't yet succeeded in writing a function to animate a display...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment