-4

i need to create a python conways game of life. i have this code given below from book "how to automate boring stuff with python" i had run this code but the output doesn't seem that the code is correct. i intended to get a result of the conway program to be in grid. can you please review the code and briefly decode it for me.

    # Conway's Game of Life
    import random, time, copy
    WIDTH = 60
    HEIGHT = 20
    # Create a list of list for the cells:
    nextCells = []
    for x in range(WIDTH):
        column = [] # Create a new column.
        for y in range(HEIGHT):
            if random.randint(0, 1) == 0:
               column.append('#') # Add a living cell.
            else:
                column.append(' ') # Add a dead cell.
        nextCells.append(column) # nextCells is a list of column lists.
   while True: # Main program loop.
       print('\n\n\n\n\n') # Separate each step with newlines.
       currentCells = copy.deepcopy(nextCells)
       # Print currentCells on the screen:
       for y in range(HEIGHT):
           for x in range(WIDTH):
               print(currentCells[x][y], end='') # Print the # or space.
           print() # Print a newline at the end of the row.
       # Calculate the next step's cells based on current step's cells:
       for x in range(WIDTH):
           for y in range(HEIGHT):
               # Get neighboring coordinates:
               # `% WIDTH` ensures leftCoord is always between 0 and WIDTH - 1
               leftCoord = (x - 1) % WIDTH
               rightCoord = (x + 1) % WIDTH
               aboveCoord = (y - 1) % HEIGHT
               belowCoord = (y + 1) % HEIGHT
               # Count number of living neighbors:
               numNeighbors = 0
               if currentCells[leftCoord][aboveCoord] == '#':
               numNeighbors += 1 # Top-left neighbor is alive.
               if currentCells[x][aboveCoord] == '#':
                   numNeighbors += 1 # Top neighbor is alive.
               if currentCells[rightCoord][aboveCoord] == '#':
                   numNeighbors += 1 # Top-right neighbor is alive.
               if currentCells[leftCoord][y] == '#':
                   numNeighbors += 1 # Left neighbor is alive.
               if currentCells[rightCoord][y] == '#':
                   numNeighbors += 1 # Right neighbor is alive.
               if currentCells[leftCoord][belowCoord] == '#':
                   numNeighbors += 1 # Bottom-left neighbor is alive.
               if currentCells[x][belowCoord] == '#':
                   numNeighbors += 1 # Bottom neighbor is alive.
               if currentCells[rightCoord][belowCoord] == '#':
                   numNeighbors += 1 # Bottom-right neighbor is alive.
               # Set cell based on Conway's Game of Life rules:
               if currentCells[x][y] == '#' and (numNeighbors == 2 or numNeighbors == 3):
                   # Living cells with 2 or 3 neighbors stay alive:
                   nextCells[x][y] = '#'
               elif currentCells[x][y] == ' ' and numNeighbors == 3:
                   # Dead cells with 3 neighbors become alive:
                   nextCells[x][y] = '#'
               else:
                    # Everything else dies or stays dead:
                    nextCells[x][y] = ' '
       time.sleep(1) # Add a 1-second pause to reduce flickering.
  • 1
    if you have a specific question about a apart of the code that's fine. but asking such broad strokes is generally frowned upon, do your own homework and if you have pain points I'm sure the community would be happy to jump in – Cptmaxon Jul 14 '22 at 05:27
  • Please edit the question to limit it to a specific problem with enough detail to identify an adequate answer. – Community Jul 14 '22 at 05:27
  • Does this answer your question? [Conway's game of life in Matlab - function returning unexpected numbers when in nested loop](https://stackoverflow.com/questions/71987154/conways-game-of-life-in-matlab-function-returning-unexpected-numbers-when-in) – Heiko Theißen Aug 06 '22 at 11:50

2 Answers2

0

Here is my code maybe it will help you and a question for you why is (-1) % 60 equal to 59(I didn't get it)?

import random, time, copy
WIDTH = 60
HEIGHT = 20

nextCells = []
for x in range(WIDTH):
    column = [] 
    for y in range(HEIGHT):
        if random.randint(0, 1) == 0:
            column.append('#')
        else:
            column.append(' ')
    nextCells.append(column) 

while True: 
    print('\n\n\n\n\n') 
    currentCells = copy.deepcopy(nextCells)

    
    for y in range(HEIGHT):
        for x in range(WIDTH):
            print(currentCells[x][y], end='') 
        print()
    for x in range(WIDTH):
        for y in range(HEIGHT):
            leftCoord=(x-1)%WIDTH
            rightCoord=(x+1)%WIDTH
            aboveCoord=(y-1)%HEIGHT
            belowCoord=(y+1)%HEIGHT

            
            numNeighbors = 0
            if currentCells[leftCoord][aboveCoord] == '#':
                numNeighbors += 1 
            if currentCells[x][aboveCoord] == '#':
                numNeighbors += 1 
            if currentCells[rightCoord][aboveCoord] == '#':
                numNeighbors += 1 
            if currentCells[leftCoord][y] == '#':
                numNeighbors += 1 
            if currentCells[rightCoord][y] == '#':
                numNeighbors += 1 
            if currentCells[leftCoord][belowCoord] == '#':
                numNeighbors += 1 
            if currentCells[x][belowCoord] == '#':
                numNeighbors += 1 
            if currentCells[rightCoord][belowCoord] == '#':
                numNeighbors += 1 


            if currentCells[x][y] == '#' and (numNeighbors == 2 or numNeighbors == 3):
            
                nextCells[x][y] = '#'
            elif currentCells[x][y] == ' ' and numNeighbors == 3:
            
                nextCells[x][y] = '#'
            else:
                
                nextCells[x][y] = ' '
    time.sleep(1)
    
Artyom
  • 31
  • 3
0

I'd like to answer Artyom's question for anyone else who is interested and stumbles across this question. I'm just going through Automate the Boring Stuff myself, and was also curious why (-1) % 60 evaluates to 59.

There are several options for implementing the division and modulus operators, both in programming and in math. Paraphrasing https://en.wikipedia.org/wiki/Modulo, when some number a (the 'dividend') is divided by another number n (the 'divisor'), we can define the quotient q and remainder r with the following equation:

a = nq + r.

Unless the remainder is exactly 0, for any a and n, there are two options for q and r which will satisfy the equation - one positive, and one negative. The positive remainder corresponds to the difference between the multiple of n immediately below the dividend a and a itself, while the negative remainder corresponds to the difference between the multiple of n immediately above the dividend a and a itself. A great visualisation and explanation of this can be seen at https://stackoverflow.com/a/67139303/21444274, which I highly recommend reading to help understand this better.

When doing basic arithmetic, we usually go with the values that give a positive r, as this corresponds to our more typical notion of what a "remainder" is (I'm sure there are many deeper number theory reasons as well!). But there's no reason why we can't go with the other value, taking the "remainder" to be the difference between the dividend and the next higher multiple of the divisor instead! To do this, we just need to use floored division, which can be simplified as "rounding down" the quotient q = a/n to the nearest integer below it.

This turns out to have a bunch of useful applications in coding, which is why the creator of Python chose to implement the modulus operator % in this way, as explained in detail here: http://python-history.blogspot.com/2010/08/why-pythons-integer-division-floors.html. One of the useful applications is the ability to use % to "wrap" co-ordinates so that they loop back on themselves at the edges, as done in the implementation of the Game of Life seen in the above code.

We can re-arrange the division equation above for r to get r = a - nq. In the case asked about here, a = -1 and n = 60. Using floored division, we get q = floor(a/n) = -1 (since -1/60 is approximately -0.02, which floors down to -1). Thus, we get r = -1 - 60 * (-1) = 59.

So to summarise - Python implements a definition for remainder that is different to what you may be used to thinking of a remainder as being, but equally mathematically valid and useful in different contexts. It's been a pretty interesting topic to deep dive on, and I mostly wanted to write this to see how well I'd understood the details, but hopefully this summary might help other beginners at least get an idea of what's going on here too. Feel free to correct/adjust me if I'm wrong on any of the details!

Eric Aya
  • 69,473
  • 35
  • 181
  • 253
dtb3
  • 1
  • 2