Skip to content

Instantly share code, notes, and snippets.

@jordanrobinson
Last active October 29, 2019 16:25
Show Gist options
  • Save jordanrobinson/10d365e0df999b0ee1bdc72fbe3e97af to your computer and use it in GitHub Desktop.
Save jordanrobinson/10d365e0df999b0ee1bdc72fbe3e97af to your computer and use it in GitHub Desktop.
Clojure Game of Life
(ns clojure-katas.game-of-life)
(defn contains-live?
[board]
(.contains (apply concat board) 1))
(defn create-grid
[size]
(repeat size (repeat size 0)))
(defn random-grid
[size]
(partition size (take (* size size) (repeatedly #(rand-int 2)))))
(defn generate-coordinate-map
[board]
(for [x (vec (take (count board) (range)))
y (vec (take (count board) (range)))]
[x y]))
(defn get-at-position
[board pos-x pos-y]
(nth (nth board pos-y ()) pos-x 0))
(defn get-left-neighbour
[board pos-x pos-y]
(get-at-position board (dec pos-x) pos-y))
(defn get-right-neighbour
[board pos-x pos-y]
(get-at-position board (inc pos-x) pos-y))
(defn get-top-neighbour
[board pos-x pos-y]
(get-at-position board pos-x (dec pos-y)))
(defn get-bottom-neighbour
[board pos-x pos-y]
(get-at-position board pos-x (inc pos-y)))
(defn count-neighbours
[board pos-x pos-y]
(+
(get-left-neighbour board pos-x pos-y)
(get-right-neighbour board pos-x pos-y)
(get-top-neighbour board pos-x pos-y)
(get-bottom-neighbour board pos-x pos-y)))
(defn should-live-or-die? [val]
(cond (< val 2) 0
(or (= 2 val) (= 3 val)) 1
(> val 3) 0))
(defn get-all-neighbours
[board]
(map #(let [[first second] %1]
(count-neighbours board first second))
(generate-coordinate-map board)))
(defn next-generation
[board]
(partition (count board) (map should-live-or-die? (get-all-neighbours board))))
(ns clojure-katas.game-of-life-test
(:require [clojure.test :refer :all]
[clojure-katas.game-of-life :refer :all]))
; Any live cell with fewer than two live neighbours dies, as if caused by under-population.
; Any live cell with two or three live neighbours lives on to the next generation.
; Any live cell with more than three live neighbours dies, as if by overcrowding.
; Any dead cell with exactly three live neighbours becomes a live cell, as if by reproduction.
(def example-empty-3x3-grid
[[0 0 0]
[0 0 0]
[0 0 0]])
(def example-1-live-cell-3x3-grid
[[0 0 0]
[0 1 0]
[0 0 0]])
(def example-2-live-cell-3x3-grid
[[0 0 0]
[1 0 1]
[0 0 0]])
(def example-3-live-cell-3x3-grid
[[0 1 0]
[1 0 1]
[0 0 0]])
(def example-4-live-cell-3x3-grid
[[0 1 0]
[1 0 1]
[0 1 0]])
(deftest create-grid_whenGivenDimensions_createsGridOfThoseDimensions
(is (= (create-grid 3) example-empty-3x3-grid)))
(deftest next-generation_whenGivenEmptyBoard_returnsEmptyBoard
(is (= (next-generation example-empty-3x3-grid) example-empty-3x3-grid)))
(deftest next-generation_whenGivenBoardWithOneLiveCell_returnsEmptyBoard
(is (= (next-generation example-1-live-cell-3x3-grid) example-empty-3x3-grid)))
(deftest contains-live_whenGivenBoardWithOneLiveCell_returnsTrue
(is (= (contains-live? example-1-live-cell-3x3-grid) true)))
(deftest count-neighbours_whenGivenTwoNeighbours_returnsTwo
(is (= (count-neighbours example-2-live-cell-3x3-grid 1 1) 2)))
(deftest count-neighbours_returnsZero_whenEdgesOfGrid
(is (= (count-neighbours example-empty-3x3-grid 0 0) 0)))
(deftest next-generation_whenGivenBoardWithTwoLiveNeighbours_CellLives
(is (= (contains-live? (next-generation example-2-live-cell-3x3-grid)) true)))
(deftest next-generation_whenGivenBoardWithThreeLiveNeighbours_CellLives
(is (= (contains-live? (next-generation example-3-live-cell-3x3-grid)) true)))
(deftest next-generation_whenGivenBoardWithFourLiveNeighbours_CellDies
(is (= (get-at-position (next-generation example-4-live-cell-3x3-grid) 1 1) 0)))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment