Last active
January 7, 2021 12:29
-
-
Save zelark/03f52736a3c35739c586d2b2453a231f to your computer and use it in GitHub Desktop.
#gameoflife #life #game
This file contains hidden or 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 zelark.small-life | |
(:require [clojure.pprint :refer [pprint]])) | |
(defn empty-board | |
"Creates a rectangular empty board of the specified width | |
and height." | |
[w h] | |
(vec (repeat w (vec (repeat h nil))))) | |
(defn populate | |
"Turns :on each of the cells specified as [y, x] coordinates." | |
[board living-cells] | |
(reduce (fn [board coordinates] | |
(assoc-in board coordinates :on)) | |
board | |
living-cells)) | |
(def glider (populate (empty-board 6 6) #{[2 0] [2 1] [2 2] [1 2] [0 1]})) | |
(pprint glider) | |
(defn neighbours | |
[[x y]] | |
(for [dx [-1 0 1] dy [-1 0 1] :when (not= 0 dx dy)] | |
[(+ dx x) (+ dy y)])) | |
(defn count-neighbours | |
[board loc] | |
(count (filter #(get-in board %) (neighbours loc)))) | |
(defn indexed-step | |
"Yields the next state of the board, using indices to determine neighbors, | |
liveness, etc." | |
[board] | |
(let [w (count board) | |
h (count (first board))] | |
(loop [new-board board | |
x 0 | |
y 0] | |
(cond | |
(>= x w) new-board | |
(>= y h) (recur new-board (inc x) 0) | |
:else | |
(let [new-liveness | |
(case (count-neighbours board [x y]) | |
2 (get-in board [x y]) | |
3 :on | |
nil)] | |
(recur (assoc-in new-board [x y] new-liveness) x (inc y))))))) | |
(pprint glider) | |
(-> (iterate indexed-step glider) | |
(nth 8) | |
pprint) | |
(defn indexed-step2 | |
[board] | |
(let [w (count board) | |
h (count (first board))] | |
(reduce | |
(fn [new-board x] | |
(reduce | |
(fn [new-board y] | |
(let [new-liveness | |
(case (count-neighbours board [x y]) | |
2 (get-in board [x y]) | |
3 :on | |
nil)] | |
(assoc-in new-board [x y] new-liveness))) | |
new-board (range h))) | |
board (range w)))) | |
(defn indexed-step3 | |
[board] | |
(let [w (count board) | |
h (count (first board))] | |
(reduce | |
(fn [new-board [x y]] | |
(let [new-liveness | |
(case (count-neighbours board [x y]) | |
2 (get-in board [x y]) | |
3 :on | |
nil)] | |
(assoc-in new-board [x y] new-liveness))) | |
board (for [x (range h) y (range w)] [x y])))) | |
;; Переход на следующий уровень | |
;; На каждом шаге выполняются следующие переходы: | |
;; - любая живая клетка, имеющая по соседству менее двух живых клеток, погибает из-за малонаселённости; | |
;; - любая живая клетка, имеющая по соседству две или три живые клетки, продолжает жить в следующем поколении; | |
;; - любая живая клетка, имеющая по соседству более трёх живых клеток, погибает из-за перенаселённости; | |
;; - в любой пустой ячейке, по соседству с которой имеется точно три живые клетки, | |
;; появляется новая живая клетка в результате размножения. | |
(defn step [cells] | |
(set (for [[loc n] (frequencies (mapcat neighbours cells)) | |
:when (or (= n 3) (and (= n 2) (cells loc)))] | |
loc))) | |
(->> #{[2 0] [2 1] [2 2] [1 2] [0 1]} | |
(iterate step) | |
(drop 8) | |
first | |
(populate (empty-board 6 6)) | |
pprint) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment