Skip to content

Instantly share code, notes, and snippets.

@Tankenstein
Last active August 28, 2015 11:34
Show Gist options
  • Save Tankenstein/9a6c7da9deede59fb70f to your computer and use it in GitHub Desktop.
Save Tankenstein/9a6c7da9deede59fb70f to your computer and use it in GitHub Desktop.
;;; simple game of life implementation in clojure
;;; (to learn a bit 'o clojure)
;;; Uku Tammet
;;; 28.08.2015
(ns gameoflife.core
(:gen-class))
(defn mip
"Shorter map-indexed lol"
[func coll]
(map-indexed func coll))
(defn row-rotate
"rotate a matrix row-wise"
[matrix rotation]
(map #(mip (fn [idx _]
(nth % (mod (+ idx rotation) (count %)))) %) matrix))
(defn column-rotate
"rotate a matrix column-wise"
[matrix rotation]
(mip (fn [idx _]
(nth matrix (mod (+ idx rotation) (count matrix)))) matrix))
(defn matrix-sum-reduce-fn
"Reduction function for matrix summation"
[frst scond]
(mip (fn [x row]
(mip (fn [y el]
(+ el (nth (nth scond x) y))) row)) frst))
(defn sum-matrices
"Sum same-sized matrices"
[matrices]
(let [length (count matrices)]
(if (>= length 2)
(reduce matrix-sum-reduce-fn matrices)
(if (= length 1)
(first matrices)
(matrices)))))
(defn life-logic-on-neighborcounts
"Execute life logic on neighborcounts and original state"
[original neighbours]
(mip (fn [x row]
(mip (fn [y el]
(if (or (= el 3)
(and (= 4 el) (= 1 (nth (nth original x) y))))
1 0)) row)) neighbours))
(defn flatten-one-level
"Flatten a seq one level"
[coll]
(mapcat #(if (sequential? %) % [%]) coll))
(defn life
"Given a matrix of 0s and 1s, return the next state of life."
[start]
(let [rotations [-1 0 1]]
(->> rotations
(map #(row-rotate start %))
(map (fn [mtrx]
(map #(column-rotate mtrx %) rotations)))
(flatten-one-level)
(sum-matrices)
(life-logic-on-neighborcounts start))))
(defn matrix-print
"Print a matrix nicely"
[matrix]
(doall (map println matrix)))
;; the starting matrix
(def starting-state
[[0 1 0 0 0 0 0 0 0 0]
[0 0 1 0 0 0 0 0 0 0]
[1 1 1 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0]])
;; the limit of how many life-s to calculate
(def limit 10)
(defn -main
"Main function called when program activated "
[& args]
(println "Starting state")
(matrix-print starting-state)
(println (str "\nComputing " limit " generations"))
(loop [state starting-state
counter limit]
(when (> counter 0)
(let [next-gen (life state)]
(println)
(matrix-print next-gen)
(recur next-gen (dec counter))))))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment