-
-
Save simon-brooke/ca9821ffd4e12da8ef23 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(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))) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(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) | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(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])) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I haven't yet succeeded in writing a function to animate a display...