Reputation: 23
Okay, so i finally get this to print, and actually do something, but the rules are not applying right? I've tried messing with the rules, but can't seem to get them to print out right, here's the snip of my rules:
nCount = 0
for i in range(x-1,x+2):
for j in range(y-1,y+2):
if not(i == x and j == y):
nCount += int(mat[i][j])
if(nCount < 2 or nCount > 3):
return 0
elif(nCount == 2 or nCount == 3):
return 1
else:
return mat[i][j]
I've tested with a regular 5x5 with 3 1's in the middle to act as an oscillator but instead of oscillating it fills the 5x5 edges with zeros like a square box then stops
Here is the rest of my coding:
import time
import os
def buildMatrix(fname):
fp = open(fname, "r")
row = fp.readlines()
matrix = []
for i in range(0, len(row), 1):
token = row[i].split(" ")
token[-1] = token[-1].replace('\n', ' ')
matrix.append(token)
fp.close()
return matrix
def getRows(mat):
return len(mat)
def getCols(mat):
return len(mat[0])
def printGen(mat): #this is what i use for printing
os.system('clear')
for i in range(0, len(mat), 1):
for j in range(0, len(mat[0]), 1):
if(mat[i][j] == 1):
print("#", sep=" ", end=" ")
else:
print(" ", sep=" ", end=" ")
print()
def nextGen(cur, nxt): #use this to update to the next matrix
for i in range(0, len(cur)-1, 1):
for j in range(0, len(cur[0])-1, 1):
nxt[i][j] = neighbors(i, j, cur)
return nxt
def neighbors(x, y, mat):
nCount = 0
for i in range(x-1,x+2):
for j in range(y-1,y+2):
if not(i == x and j == y):
nCount += int(mat[i][j])
if(nCount < 2 or nCount > 3):
return 0
elif(nCount == 2 or nCount ==3):
return 1
else:
return mat[i][j]
This isnt all my code, as im still importing all this to another repo and running it from that repo, but the other part i have done
Upvotes: 1
Views: 1902
Reputation: 280973
elif(nCount == 2,3):
This doesn't do what you want. This builds a 2-element tuple whose first element is the value of nCount == 2
, and whose second element is 3, then converts this tuple to a boolean to decide which way to go. If you wanted to check whether nCount
was equal to either 2 or 3, you could use
elif nCount in (2, 3):
but it's redundant, since nCount
must be one of those for control flow to reach the elif
. Of course, this isn't correct for implementing the rules of Life; what you want is
elif nCount == 3:
A cell keeps its current live/dead status if surrounded by 2 other live cells. There have to be exactly 3 live cells around it for it to be alive in the next generation regardless of its current life status.
Upvotes: 3
Reputation: 4674
It looks like your code isn't making a copy first, so the results of a birth or death are effecting themselves. Try with a copy:
import numpy
# this function does all the work
def play_life(a):
xmax, ymax = a.shape
b = a.copy() # copy current life grid
for x in range(xmax):
for y in range(ymax):
n = numpy.sum(a[max(x - 1, 0):min(x + 2, xmax), max(y - 1, 0):min(y + 2, ymax)]) - a[x, y]
if a[x, y]:
if n < 2 or n > 3:
b[x, y] = 0 # living cells with <2 or >3 neighbors die
elif n == 3:
b[x, y] = 1 # dead cells with 3 neighbors ar born
return(b)
life = numpy.zeros((5, 5), dtype=numpy.byte)
# place starting conditions here
life[2, 1:4] = 1 # middle three in middle row to 1
# now let's play
print(life)
for i in range(3):
life = play_life(life)
print(life)
I also used numpy
for speed. Note that the case for a live cell with 2 or 3 neighbors is taken care of when the copy is made. Here are the results of this test case:
[[0 0 0 0 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 1 0 0]
[0 0 1 0 0]
[0 0 1 0 0]
[0 0 0 0 0]]
[[0 0 0 0 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 1 0 0]
[0 0 1 0 0]
[0 0 1 0 0]
[0 0 0 0 0]]
Now, if you don't have numpy
, then you can use a "2D" array like this:
# this function does all the work
def play_life(a):
xmax = len(a)
ymax = len(a[0])
b = [[cell for cell in row] for row in life]
for x in range(xmax):
for y in range(ymax):
n = 0
for i in range(max(x - 1, 0), min(x + 2, xmax)):
for j in range(max(y - 1, 0), min(y + 2, ymax)):
n += a[i][j]
n -= a[x][y]
if a[x][y]:
if n < 2 or n > 3:
b[x][y] = 0 # living cells with <2 or >3 neighbors die
elif n == 3:
b[x][y] = 1 # dead cells with 3 neighbors ar born
return(b)
# this function just prints the board
def show_life(a):
print('\n'.join([' '.join([str(cell) for cell in row]) for row in life]) + '\n')
# create board
x_size, y_size = (5, 5)
life = [[0 for y in range(y_size)] for x in range(x_size)]
# place starting conditions here
for x in range(1, 4): life[x][2] = 1 # middle three in middle row to 1
# now let's play
show_life(life)
for i in range(3):
life = play_life(life)
show_life(life)
That outputs the following for the test case:
0 0 0 0 0
0 0 1 0 0
0 0 1 0 0
0 0 1 0 0
0 0 0 0 0
0 0 0 0 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 1 0 0
0 0 1 0 0
0 0 1 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 1 1 1 0
0 0 0 0 0
0 0 0 0 0
Upvotes: 2