<SYSTEM_TASK:>
Given the following text description, write Python code to implement the functionality described below step by step
<END_TASK>
<USER_TASK:>
Description:
Step5:  Conway's Game of Life
Conway's Game of Life is a classic demonstration of emergence, where higher level patterns form from a few simple rules. Fantastic patterns emerge when the game is let to run long enough.
The rules here, to borrow from Wikipedia, are as follows
Step6:  A text-based example
To plot a simple version of Conway's Game of Life, we can use a print function
Step8:  pydeck implementation
We can use either the PointCloudLayer or ScatterplotLayer from deck.gl to visualize the game.
Step9:  To play the game over time, we call update in a loop.
<ASSISTANT_TASK:>
Python Code:
import random
def new_board(x, y, num_live_cells=2, num_dead_cells=3):
    Initializes a board for Conway's Game of Life
    board = []
    for i in range(0, y):
        # Defaults to a 3:2 dead cell:live cell ratio
        board.append([random.choice([0] * num_dead_cells + [1] * num_live_cells) for _ in range(0, x)])
    return board
        
def get(board, x, y):
    Return the value at location (x, y) on a board, wrapping around if out-of-bounds
    return board[y % len(board)][x % len(board[0])]
def assign(board, x, y, value):
    Assigns a value at location (x, y) on a board, wrapping around if out-of-bounds
    board[y % len(board)][x % len(board[0])] = value
def count_neighbors(board, x, y):
    Counts the number of living neighbors a cell at (x, y) on a board has
    return sum([
        get(board, x - 1, y),
        get(board, x + 1, y),
        get(board, x, y - 1),
        get(board, x, y + 1),
        get(board, x + 1, y + 1),
        get(board, x + 1, y - 1),
        get(board, x - 1, y + 1),
        get(board, x - 1, y - 1)])
def process_life(board):
    Creates the next iteration from a passed state of Conway's Game of Life
    next_board = new_board(len(board[0]), len(board))
    for y in range(0, len(board)):
        for x in range(0, len(board[y])):
            num_neighbors = count_neighbors(board, x, y)
            is_alive = get(board, x, y) == 1
            if num_neighbors < 2 and is_alive:
                assign(next_board, x, y, 0)
            elif 2 <= num_neighbors <= 3 and is_alive:
                assign(next_board, x, y, 1)
            elif num_neighbors > 3 and is_alive:
                assign(next_board, x, y, 0)
            elif num_neighbors == 3 and not is_alive:
                assign(next_board, x, y, 1)
            else:
                assign(next_board, x, y, 0)
    return next_board
Explanation: Conway's Game of Life
Conway's Game of Life is a classic demonstration of emergence, where higher level patterns form from a few simple rules. Fantastic patterns emerge when the game is let to run long enough.
The rules here, to borrow from Wikipedia, are as follows:
Any live cell with fewer than two live neighbours dies, as if by underpopulation.
Any live cell with two or three live neighbours lives on to the next generation.
Any live cell with more than three live neighbours dies, as if by overpopulation.
Any dead cell with exactly three live neighbours becomes a live cell, as if by reproduction.
Below is a simple Conway's Game of Life implementation:
End of explanation
from IPython.display import clear_output
import time
def draw_board(board):
    res = ''
    for row in board:
        for col in row:
            if col == 1:
                res += '* '
            else:
                res += '  '
        res += '\n'
    return res
board = new_board(20, 20)
NUM_ITERATIONS = 100
for i in range(0, NUM_ITERATIONS):
    print('Iteration ' + str(i + 1))
    board = process_life(board)
    res = draw_board(board)
    print(res)
    time.sleep(0.1)
    clear_output(wait=True)
Explanation: A text-based example
To plot a simple version of Conway's Game of Life, we can use a print function:
End of explanation
import numpy as np
import pandas as pd
import pydeck as deck
PINK = [155, 155, 255, 245]
PURPLE = [255, 155, 255, 245]
SCALING_FACTOR = 1000.0
def convert_board_to_df(board):
    Makes the board matrix into a list for easier processing
    rows = []
    for x in range(0, len(board[0])):
        for y in range(0, len(board)):
            rows.append([[x / SCALING_FACTOR, y / SCALING_FACTOR], PURPLE if board[y][x] else PINK])
    return pd.DataFrame(rows, columns=['position', 'color'])
board = new_board(30, 30)
records = convert_board_to_df(board)
layer = deck.Layer(
    'PointCloudLayer',
    records,
    get_position='position',
    get_color='color',
    get_radius=40)
view_state = deck.ViewState(latitude=0.00, longitude=0.00, zoom=13, bearing=44, pitch=45)
r = deck.Deck(layers=[layer], initial_view_state=view_state, map_style='')
r.show()
Explanation: pydeck implementation
We can use either the PointCloudLayer or ScatterplotLayer from deck.gl to visualize the game.
End of explanation
NUM_ITERATIONS = 100
display(r.show())
for i in range(0, NUM_ITERATIONS):
    board = process_life(board)
    records = convert_board_to_df(board)
    layer.data = records
    r.update()
    time.sleep(0.1)
Explanation: To play the game over time, we call update in a loop.
End of explanation
<END_TASK>