[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Conway's Game of Life (cellular automata)



Thanks, Anton.   I would say you had better design than my version,
and chose better names, but that you left open the question of how
HTDP would propose to design the Life program.
   
   It looks as though you chose quite early on to implement the game
   purely in terms of lists.  This seems to have quite strongly
   affected the overall structure of the program.

Sure did!  That's what I think the TLS/TSS functional programming
style is: consume lists.  

Scheme doesn't have matrices, so I first implemented a Life board-game
as a vector of strings.  Strings helped with the IO, otherwise a
vector of vector would've been the same.  But I ran into all kinds of
mutability problems, so the list of list functional version was easier
to code up!  (Well, it was the 2nd time around.)  

   At this point, I'll come out of the mathematical closet and admit that I'd
   just like to implement this using a simple, coordinate-addressable 2D
   matrix.  

I feel sure that HTDP would frown on that.  But that was my 1st choice
as well.  There's a lot of talk in HTDP about OOP, and there are a lot
of board games in HTDP.  We ought to figure this out.  It's hard for
me to follow HTDP board games because I don't have the teachpacks.

     ; returns game board containing the next generation based on the specified
     ; board
     (define (next-generation game-board)
   
       ; returns next state of cell with current value as
       ; specified, based on the state of surrounding cells
       (define (new-cell-state cell-value x y)
         (let ((count (count-surrounding-black-cells cell-value x y)))
           (if (or (= count 3) (and (isblack? cell-value) (= count 2)))
               black-cell-value
               white-cell-value)))
   
       (define (count-surrounding-black-cells cell-value x y)
         (- (matrix-sum board (- x 1) (+ x 2) (- y 1) (+ y 2))
           cell-value))
   
       (board-map new-cell-state game-board))
   
   
     (define (isblack? cell)	(= cell black-cell-value))
     (define (iswhite? cell)	(= cell white-cell-value))	 ; for completeness
   
     ; below functions are implementation-specific, but fairly innocent
     (define white-cell-value 0)
     (define black-cell-value 1)
   
     (define (board-map proc board)
       (matrix-map proc board 0 (board-width board) 0 (board-height board)))
   


     (define (count-surrounding-black-cells cell-value x y)
       (- (matrix-sum board (- x 1) (+ x 2) (- y 1) (+ y 2))
          cell-value))
   

I like this, Anton!  Your definition of `count' is simpler than mine.
Your `count-surrounding-black-cells' is maybe too cute, why not
redefine `matrix-sum' to not add up the "origin" of your range, then
`count-surrounding-black-cells'  doesn't need `cell-value' as an
argument. 

BTW I think cellular automata all use the nearest neighbors, so we
wouldn't be summing over a larger range.  But much different functions
are used on the nearest neighbors.  Just keeping it to 0s and 1s, I'm
thinking of 2^{2^9} such `new-cell-state' functions, there are 2^9 0/1
configurations for the cell & its nearest neighbors, and each
configuration get sent by `new-cell-state' to either 0 or 1.

This shows an inelegancy of the x/y approach: your function
`new-cell-state' does "the same thing" no matter what x & y are.  Of
course, the cell & its nearest neighbors change as x & y vary, but the
function in 2^{2^9} is the same everywhere on the board.  It's not
like we calculate one way in Germany and a different way in the US.