Question

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

Was it helpful?

Solution

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.

OTHER TIPS

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
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top