(ns game-of-life.core (:require [clojure.set :only [union difference]])) (defn neighbors [[x-cell y-cell]] (set (for [x (range (dec x-cell) (+ x-cell 2)) y (range (dec y-cell) (+ y-cell 2)) :when (not (and (= x x-cell) (= y y-cell)))] [x y]))) (defn num-neighbors-being-a-cell [cell cells] (count (filter (neighbors cell) cells))) (defn will-go-on-being-a-cell? [num-neighbors-being-a-cell] (or (= num-neighbors-being-a-cell 3) (= num-neighbors-being-a-cell 2))) (defn will-be-a-cell? [num-neighbors-being-a-cell] (= num-neighbors-being-a-cell 3)) (defn candidates-to-be-a-cell [cells] (clojure.set/difference (reduce clojure.set/union (map neighbors cells)) (set cells))) (defn keep-being-cells [cells] (set (filter #(will-go-on-being-a-cell? (num-neighbors-being-a-cell % cells)) cells))) (defn new-cells [cells] (set (filter #(will-be-a-cell? (num-neighbors-being-a-cell % cells)) (candidates-to-be-a-cell cells)))) (defn next-cells [cells] (clojure.set/union (keep-being-cells cells) (new-cells cells))) (defn game-of-life [cells num-iter] (take num-iter (iterate next-cells cells)))