Skip to content

Instantly share code, notes, and snippets.

@mdwhatcott
Last active September 13, 2021 15:12
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mdwhatcott/0689d65c83edd37d3b178eff96898280 to your computer and use it in GitHub Desktop.
Save mdwhatcott/0689d65c83edd37d3b178eff96898280 to your computer and use it in GitHub Desktop.
The Game of Life Kata
(ns kata.life)
(defn neighbors-of [[x y]]
(for [Y (range (dec y) (+ 2 y))
X (range (dec x) (+ 2 x))
:when (not= [x y] [X Y])] [X Y]))
(defn count-active-neighbors [cell grid]
(->> cell neighbors-of set (filter grid) count))
(defn update-cell [cell grid]
(let [n (count-active-neighbors cell grid)]
(cond (= n 3) cell
(not= n 2) nil
(grid cell) cell)))
(defn evolve [grid]
(->> (mapcat neighbors-of grid)
(map #(update-cell % grid))
(remove nil?) set))
(ns kata.life-spec
(:require [speclj.core :refer :all]
[kata.life :refer :all]))
(def cell [0 0])
(defn take-neighbors [n] (->> cell neighbors-of shuffle (take n) set))
(describe "Conway's Game of Life"
(it "has awareness of the neighbors of a cell"
(should= #{[-1 -1] [0 -1] [1 -1]
[-1 0] #_cell [1 0]
[-1 1] [0 1] [1 1]} (take-neighbors 8)))
(for [n (range 9)]
(it (format "has awareness of the %d active neighbors of a cell" n)
(let [grid (conj (take-neighbors n) [42 43])]
(should= n (count-active-neighbors cell grid)))))
(for [n [0 1 #_2 #_3 4 5 6 7 8]]
(it (format "discards active cells with %d active neighbors" n)
(let [grid (conj (take-neighbors n) cell)]
(should= nil (update-cell cell grid)))))
(for [n [2 3]]
(it (format "retains active cells with %d active neighbors" n)
(let [grid (conj (take-neighbors n) cell)]
(should= cell (update-cell cell grid)))))
(it "revives inactive cells with 3 active neighbors"
(let [grid (take-neighbors 3)]
(should= cell (update-cell cell grid))))
(for [n [0 1 2 #_3 4 5 6 7 8]]
(it (format "ignores inactive cells with %d active neighbors" n)
(let [grid (take-neighbors n)]
(should= nil (update-cell cell grid)))))
(it "evolves an entire grid of cells through multiple iterations"
(let [oscillator [#{[0 1] [1 1] [2 1]}
#{[1 0] [1 1] [1 2]}]]
(should= (take 8 (cycle oscillator))
(take 8 (iterate evolve (first oscillator)))))))
Conway's Game of Life
- has awareness of the neighbors of a cell
- has awareness of the 0 active neighbors of a cell
- has awareness of the 1 active neighbors of a cell
- has awareness of the 2 active neighbors of a cell
- has awareness of the 3 active neighbors of a cell
- has awareness of the 4 active neighbors of a cell
- has awareness of the 5 active neighbors of a cell
- has awareness of the 6 active neighbors of a cell
- has awareness of the 7 active neighbors of a cell
- has awareness of the 8 active neighbors of a cell
- discards active cells with 0 active neighbors
- discards active cells with 1 active neighbors
- discards active cells with 4 active neighbors
- discards active cells with 5 active neighbors
- discards active cells with 6 active neighbors
- discards active cells with 7 active neighbors
- discards active cells with 8 active neighbors
- retains active cells with 2 active neighbors
- retains active cells with 3 active neighbors
- revives inactive cells with 3 active neighbors
- ignores inactive cells with 0 active neighbors
- ignores inactive cells with 1 active neighbors
- ignores inactive cells with 2 active neighbors
- ignores inactive cells with 4 active neighbors
- ignores inactive cells with 5 active neighbors
- ignores inactive cells with 6 active neighbors
- ignores inactive cells with 7 active neighbors
- ignores inactive cells with 8 active neighbors
- evolves an entire grid of cells through multiple iterations
Finished in 0.00568 seconds
29 examples, 0 failures
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment