# Game of Life using math/array

Since the use of `math/array` came up recently in a topic here, I thought, I'll have a look at the package and see how difficult it would be to implement the game of life (Conway's Game of Life - Wikipedia) using it. Turns out it is pretty simple:

First, here is a function which encodes the game rules for an individual cell (this has nothing to do with math/array)

``````(define (game-rules cell neighbor-count)
(cond
;; Any live cell with fewer than two live neighbours dies, as if by
;; underpopulation.
((and (equal? cell 1) (< neighbor-count 2)) 0)
;; Any live cell with two or three live neighbors lives on to the next
;; generation.
((and (equal? cell 1) (or (= neighbor-count 2) (= neighbor-count 3))) 1)
;; Any live cell with more than three live neighbors dies, as if by
;; overpopulation.
((and (equal? cell 1) (> neighbor-count 3)) 0)
;; Any dead cell with exactly three live neighbours becomes a live cell,
;; as if by reproduction.
((and (equal? cell 0) (= neighbor-count 3)) 1)
;; All else, cell remains unchanged
(else cell)))
``````

And here is the code to run the simulation, note that the code operates on arrays a whole, without referencing individual elements:

``````(define initial ;; initial configuration (this is a glider pattern)
(array
#[#[0 0 0 0 0 0 0 0 0 0]
#[0 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]]))

(define (rol a dimension)               ; rotate left
(define n (vector-ref (array-shape a) dimension))
(append (list (sub1 n)) (build-list (sub1 n) values)))

(define (ror a dimension)               ; rotate right
(define n (vector-ref (array-shape a) dimension))
(append (build-list (sub1 n) add1) '(0)))

(define shifts
`((,(::) ,(rol initial 1))            ; left
(,(::) ,(ror initial 1))            ; right
(,(rol initial 0) ,(::))            ; up
(,(ror initial 0) ,(::))            ; down
(,(rol initial 0) ,(rol initial 1)) ; up-left
(,(rol initial 0) ,(ror initial 1)) ; up-right
(,(ror initial 0) ,(rol initial 1)) ; down-left
(,(ror initial 0) ,(ror initial 1)) ; down-right
))

(define (neighbour-count a)
(define ns (map (lambda (shift) (array-slice-ref a shift)) shifts))
(apply array-map + ns))

(define (advance a) ;; advance the world one time unit
(array-map game-rules a (neighbour-count a)))
``````

And here is what it looks like (this animation is with a more complex pattern): Here is the full program: game-of-life.rkt · GitHub

Enjoy!
Alex.

7 Likes