Conway's Game of Life: Difference between revisions

Jump to navigation Jump to search
Line 155: Line 155:
The grid in the centre is our original grid, and the others give the neighbours above, below, left, right and diagonally.
The grid in the centre is our original grid, and the others give the neighbours above, below, left, right and diagonally.
=== Summing it up ===
=== Summing it up ===
Now we can find out how many neighbours each cell in the original grid has by summing the corresponding elements in each of the 9 grids. For a live cell this will give us 1 more than the number of neighbours - e.g. a 4 in the result means a cell has three neighbours. For a dead cell the result is just the number of neighbours:
Now we can find out how many neighbours each cell in the original grid has by summing ([[Plus]] [[Reduce]]) the corresponding elements in each of the 9 grids. We sum all the grids at once by [[ravel]]ling the [[shape]] <source lang=apl inline>3 3</source> [[matrix]] of grids to obtain a 9-element [[vector]]; otherwise [[Reduce]] would only allow us to sum rows or columns. Here APL's representation of [[Boolean]]s as numbers is advantageous, since otherwise counting the number of true values would require converting them to numbers or using conditional logic. For a live cell the sum is 1 more than the number of neighbours—for example, a 4 in the result means a cell has three neighbours. For a dead cell the result is just the number of neighbours:


<source lang=apl>
<source lang=apl>
Line 175: Line 175:
This means that all cells which might be live in the next generation will have a sum of 3 (from the first rule) or 3 or 4 (from the second rule).
This means that all cells which might be live in the next generation will have a sum of 3 (from the first rule) or 3 or 4 (from the second rule).


So we're interested in cells with a sum of 3 or 4, which we can find as follows:
So we're interested in cells with a sum of 3 or 4. We can find these cells with a simple application of [[Equal to]], relying on [[pervasion]] and [[scalar extension]] to distribute the data properly. The result of the last step was a [[scalar]] containing one grid; when paired with the [[vector]] <source lang=apl inline>3 4</source> it is extended to give two grids. Within each grid 3 and 4 are compared with every element by scalar extension again. If the right argument were a flat array rather than being [[enclose]]d, we could obtain a similar, but flat, result using another [[Outer Product]].


<source lang=apl>
<source lang=apl>
Line 188: Line 188:
</source>
</source>


The next step is best understood by first considering the two scores 4 and 3 separately
The next step is best understood by first considering the two scores 4 and 3 separately.


(a) A score of 4 corresponds either to a live cell with three neighbours or a dead cell with four neighbours. Only in the former case do we get a cell in the next generation - i.e. we get a cell if the score is 4 ''and'' the cell is currently live. Here we're using APL's [[And]] function, <source lang=apl inline>∧</source>
(a) A score of 4 corresponds either to a live cell with three neighbours or a dead cell with four neighbours. Only in the former case do we get a cell in the next generation - i.e. we get a cell if the score is 4 ''and'' the cell is currently live. Here we're using APL's [[And]] function, <source lang=apl inline>∧</source>
Line 237: Line 237:
└─────────┘
└─────────┘
</source>
</source>
=== Refactoring ===
=== Refactoring ===
But we can take advantage of APL's [[Inner Product]] operator to do the ''and'' operations of each test and then ''or'' the result - the <source lang=apl inline>∨.∧</source> in the following:
But we can take advantage of APL's [[Inner Product]] operator to do the ''and'' operations of each test and then ''or'' the result - the <source lang=apl inline>∨.∧</source> in the following:

Navigation menu