Skip to content

Instantly share code, notes, and snippets.

@zelark
Last active January 7, 2021 12:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save zelark/03f52736a3c35739c586d2b2453a231f to your computer and use it in GitHub Desktop.
Save zelark/03f52736a3c35739c586d2b2453a231f to your computer and use it in GitHub Desktop.
#gameoflife #life #game
(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