Last active
August 29, 2015 14:00
-
-
Save mowat27/7228baa672553cf32a2d to your computer and use it in GitHub Desktop.
Glasgow Clojurians - 1 May 2014
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 game-of-life.core | |
(:require [clojure.set :as set])) | |
(def example-world #{[2 1] [-1 2] [1 4]}) | |
(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)]}) | |
(defn count-live-neighbours [world coords] | |
(count (set/intersection world (neighbours coords)))) | |
(defn survives? [world coords] | |
(let [n (count-live-neighbours world coords)] | |
(or | |
(and (contains? world coords) (or (= n 2) (= n 3))) | |
(= n 3)))) | |
(defn extents [world] | |
(let [[min-x max-x min-y max-y] (->> [(map first world) (map last world)] | |
(map (juxt #(apply min %) #(apply max %))) | |
(apply concat))] | |
[(range (dec min-x) (+ 2 max-x)) | |
(range (dec min-y) (+ 2 max-y))])) | |
(defn next-gen [world] | |
(set (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 (take 5 (iterate next-gen #{[1 2] [2 2] [3 2]}))) | |
(= expected actual) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
A little macro to help with all the min-x and max-y functions:
(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))
(OK, it doesn't help much, but illustrates writing macros)