From 743c0ca20c0994447480e9132c8f9023f8011e58 Mon Sep 17 00:00:00 2001 From: jenra Date: Thu, 8 Oct 2020 10:24:48 -0400 Subject: [PATCH 01/17] Created conways_game_of_life.py --- cellular_automata/conways_game_of_life.py | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 cellular_automata/conways_game_of_life.py diff --git a/cellular_automata/conways_game_of_life.py b/cellular_automata/conways_game_of_life.py new file mode 100644 index 000000000000..821432ef1dd7 --- /dev/null +++ b/cellular_automata/conways_game_of_life.py @@ -0,0 +1,5 @@ +""" +Conway's Game of Life implemented in Python. +""" + + From f6e2b387a38885832b95e014535369a546cf41c6 Mon Sep 17 00:00:00 2001 From: jenra Date: Thu, 8 Oct 2020 10:39:12 -0400 Subject: [PATCH 02/17] Added new_generation(list[int[int]]) -> list[list[int]] --- cellular_automata/conways_game_of_life.py | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/cellular_automata/conways_game_of_life.py b/cellular_automata/conways_game_of_life.py index 821432ef1dd7..0f34c1acfc55 100644 --- a/cellular_automata/conways_game_of_life.py +++ b/cellular_automata/conways_game_of_life.py @@ -2,4 +2,25 @@ Conway's Game of Life implemented in Python. """ +from __future__ import annotations +def new_generation(cells: list[list[int]]) -> list[list[int]]: + next_generation = [] + for i in range(len(cells)): + next_generation_row = [] + for j in range(len(cells[i])): + neighbour_count = cells[i - 1][j - 1] \ + + cells[i - 1][j + 0] \ + + cells[i - 1][j + 1] \ + + cells[i + 0][j - 1] \ + + cells[i + 1][j + 1] \ + + cells[i + 1][j - 1] \ + + cells[i + 1][j + 0] \ + + cells[i + 1][j + 1] + alive = cells[i][j] == 1 + if (alive and 2 <= neighbour_count <= 3) or not alive and neighbour_count == 3: + next_generation_row.append(1) + else: + next_generation_row.append(0) + next_generation.append(next_generation_row) + return next_generation From 1aff5ad43dfe032e4b202b542b97f00cf5cfe652 Mon Sep 17 00:00:00 2001 From: jenra Date: Thu, 8 Oct 2020 10:46:35 -0400 Subject: [PATCH 03/17] Added glider example --- cellular_automata/conways_game_of_life.py | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/cellular_automata/conways_game_of_life.py b/cellular_automata/conways_game_of_life.py index 0f34c1acfc55..84c8a61d102a 100644 --- a/cellular_automata/conways_game_of_life.py +++ b/cellular_automata/conways_game_of_life.py @@ -4,6 +4,27 @@ from __future__ import annotations +# Define glider example +GLIDER = [ + [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 1, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], +] + + def new_generation(cells: list[list[int]]) -> list[list[int]]: next_generation = [] for i in range(len(cells)): From e4047346eb69183957a060f65ed62027cdb58ac6 Mon Sep 17 00:00:00 2001 From: jenra Date: Thu, 8 Oct 2020 10:51:49 -0400 Subject: [PATCH 04/17] Added comments and shortened glider example --- cellular_automata/conways_game_of_life.py | 32 +++++++++++------------ 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/cellular_automata/conways_game_of_life.py b/cellular_automata/conways_game_of_life.py index 84c8a61d102a..9a4f84b32e20 100644 --- a/cellular_automata/conways_game_of_life.py +++ b/cellular_automata/conways_game_of_life.py @@ -1,27 +1,20 @@ """ Conway's Game of Life implemented in Python. +https://en.wikipedia.org/wiki/Conway%27s_Game_of_Life """ from __future__ import annotations # Define glider example GLIDER = [ - [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - [0, 0, 1, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [0, 1, 0, 0, 0, 0, 0, 0], + [0, 0, 1, 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, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0] ] @@ -30,6 +23,7 @@ def new_generation(cells: list[list[int]]) -> list[list[int]]: for i in range(len(cells)): next_generation_row = [] for j in range(len(cells[i])): + # Get the number of live neighbours neighbour_count = cells[i - 1][j - 1] \ + cells[i - 1][j + 0] \ + cells[i - 1][j + 1] \ @@ -38,10 +32,16 @@ def new_generation(cells: list[list[int]]) -> list[list[int]]: + cells[i + 1][j - 1] \ + cells[i + 1][j + 0] \ + cells[i + 1][j + 1] + + # Rules of the game of life (excerpt from Wikipedia): + # 1. Any live cell with two or three live neighbours survives. + # 2. Any dead cell with three live neighbours becomes a live cell. + # 3. All other live cells die in the next generation. Similarly, all other dead cells stay dead. alive = cells[i][j] == 1 if (alive and 2 <= neighbour_count <= 3) or not alive and neighbour_count == 3: next_generation_row.append(1) else: next_generation_row.append(0) + next_generation.append(next_generation_row) return next_generation From 64bfe9260f365ad767b40167f8cfff6a63e3acff Mon Sep 17 00:00:00 2001 From: jenra Date: Thu, 8 Oct 2020 11:04:53 -0400 Subject: [PATCH 05/17] Fixed index out of bounds error --- cellular_automata/conways_game_of_life.py | 25 +++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/cellular_automata/conways_game_of_life.py b/cellular_automata/conways_game_of_life.py index 9a4f84b32e20..d8d2348a3e4f 100644 --- a/cellular_automata/conways_game_of_life.py +++ b/cellular_automata/conways_game_of_life.py @@ -24,14 +24,23 @@ def new_generation(cells: list[list[int]]) -> list[list[int]]: next_generation_row = [] for j in range(len(cells[i])): # Get the number of live neighbours - neighbour_count = cells[i - 1][j - 1] \ - + cells[i - 1][j + 0] \ - + cells[i - 1][j + 1] \ - + cells[i + 0][j - 1] \ - + cells[i + 1][j + 1] \ - + cells[i + 1][j - 1] \ - + cells[i + 1][j + 0] \ - + cells[i + 1][j + 1] + neighbour_count = 0 + if i > 0 and j > 0: + neighbour_count += cells[i - 1][j - 1] + if i > 0: + neighbour_count += cells[i - 1][j ] + if i > 0 and j < len(cells[i]) - 1: + neighbour_count += cells[i - 1][j + 1] + if j > 0: + neighbour_count += cells[i ][j - 1] + if j < len(cells[i]) - 1: + neighbour_count += cells[i ][j + 1] + if i < len(cells) - 1 and j > 0: + neighbour_count += cells[i + 1][j - 1] + if i < len(cells) - 1: + neighbour_count += cells[i + 1][j ] + if i < len(cells) - 1 and j < len(cells[i]) - 1: + neighbour_count += cells[i + 1][j + 1] # Rules of the game of life (excerpt from Wikipedia): # 1. Any live cell with two or three live neighbours survives. From 7dbe70929b854057f62a8e26b0508efe717ef92a Mon Sep 17 00:00:00 2001 From: jenra Date: Thu, 8 Oct 2020 11:16:54 -0400 Subject: [PATCH 06/17] Added test --- cellular_automata/conways_game_of_life.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/cellular_automata/conways_game_of_life.py b/cellular_automata/conways_game_of_life.py index d8d2348a3e4f..edb39015cf64 100644 --- a/cellular_automata/conways_game_of_life.py +++ b/cellular_automata/conways_game_of_life.py @@ -19,6 +19,10 @@ def new_generation(cells: list[list[int]]) -> list[list[int]]: + """ + >>> new_generation(GLIDER) + [[0, 0, 0, 0, 0, 0, 0, 0], [1, 0, 1, 0, 0, 0, 0, 0], [0, 1, 1, 0, 0, 0, 0, 0], [0, 1, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0]] + """ next_generation = [] for i in range(len(cells)): next_generation_row = [] @@ -47,6 +51,8 @@ def new_generation(cells: list[list[int]]) -> list[list[int]]: # 2. Any dead cell with three live neighbours becomes a live cell. # 3. All other live cells die in the next generation. Similarly, all other dead cells stay dead. alive = cells[i][j] == 1 + if neighbour_count: + print("%i, %i has %i neighbours" % (i, j, neighbour_count)) if (alive and 2 <= neighbour_count <= 3) or not alive and neighbour_count == 3: next_generation_row.append(1) else: From 0d8df7f13e35b768a28ecedf864e1d48df20afd5 Mon Sep 17 00:00:00 2001 From: jenra Date: Thu, 8 Oct 2020 12:00:28 -0400 Subject: [PATCH 07/17] Added blinker example --- cellular_automata/conways_game_of_life.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/cellular_automata/conways_game_of_life.py b/cellular_automata/conways_game_of_life.py index edb39015cf64..ced805fb3978 100644 --- a/cellular_automata/conways_game_of_life.py +++ b/cellular_automata/conways_game_of_life.py @@ -17,11 +17,19 @@ [0, 0, 0, 0, 0, 0, 0, 0] ] +# Define blinker example +BLINKER = [ + [0, 1, 0], + [0, 1, 0], + [0, 1, 0] +] def new_generation(cells: list[list[int]]) -> list[list[int]]: """ >>> new_generation(GLIDER) [[0, 0, 0, 0, 0, 0, 0, 0], [1, 0, 1, 0, 0, 0, 0, 0], [0, 1, 1, 0, 0, 0, 0, 0], [0, 1, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0]] + >>> new_generation(BLINKER) + [[0, 0, 0], [1, 1, 1], [0, 0, 0]] """ next_generation = [] for i in range(len(cells)): From c33f0ef9afedc6f3216b541debb5d5e54dd1926e Mon Sep 17 00:00:00 2001 From: jenra Date: Thu, 8 Oct 2020 14:42:05 -0400 Subject: [PATCH 08/17] Added ability to generate images --- cellular_automata/conways_game_of_life.py | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/cellular_automata/conways_game_of_life.py b/cellular_automata/conways_game_of_life.py index ced805fb3978..718fb21f1a8c 100644 --- a/cellular_automata/conways_game_of_life.py +++ b/cellular_automata/conways_game_of_life.py @@ -5,6 +5,8 @@ from __future__ import annotations +from PIL import Image + # Define glider example GLIDER = [ [0, 1, 0, 0, 0, 0, 0, 0], @@ -59,8 +61,6 @@ def new_generation(cells: list[list[int]]) -> list[list[int]]: # 2. Any dead cell with three live neighbours becomes a live cell. # 3. All other live cells die in the next generation. Similarly, all other dead cells stay dead. alive = cells[i][j] == 1 - if neighbour_count: - print("%i, %i has %i neighbours" % (i, j, neighbour_count)) if (alive and 2 <= neighbour_count <= 3) or not alive and neighbour_count == 3: next_generation_row.append(1) else: @@ -68,3 +68,17 @@ def new_generation(cells: list[list[int]]) -> list[list[int]]: next_generation.append(next_generation_row) return next_generation + +if __name__ == "__main__": + cells = GLIDER + images = [] + for i in range(16): + img = Image.new("RGB", (len(cells), len(cells[0]))) + pixels = img.load() + for x in range(len(cells)): + for y in range(len(cells[0])): + colour = 255 - cells[x][y] * 255 + pixels[x, y] = (colour, colour, colour) + images.append(img) + cells = new_generation(cells) + images[0].save("out.gif", save_all=True, append_images=images[1:]) From 2de3779856653b687cf139f5886a095c1db32b26 Mon Sep 17 00:00:00 2001 From: jenra Date: Thu, 8 Oct 2020 14:46:23 -0400 Subject: [PATCH 09/17] Moved image generating code into a separate function --- cellular_automata/conways_game_of_life.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/cellular_automata/conways_game_of_life.py b/cellular_automata/conways_game_of_life.py index 718fb21f1a8c..ac6c546ff1b2 100644 --- a/cellular_automata/conways_game_of_life.py +++ b/cellular_automata/conways_game_of_life.py @@ -69,16 +69,19 @@ def new_generation(cells: list[list[int]]) -> list[list[int]]: next_generation.append(next_generation_row) return next_generation -if __name__ == "__main__": - cells = GLIDER +def generate_images(cells: list[list[int]], frames) -> list[Image.Image]: images = [] - for i in range(16): - img = Image.new("RGB", (len(cells), len(cells[0]))) + for i in range(frames): + img = Image.new("RGB", (len(cells[0]), len(cells))) pixels = img.load() for x in range(len(cells)): for y in range(len(cells[0])): - colour = 255 - cells[x][y] * 255 + colour = 255 - cells[y][x] * 255 pixels[x, y] = (colour, colour, colour) images.append(img) cells = new_generation(cells) + return images + +if __name__ == "__main__": + images = generate_images(GLIDER, 16) images[0].save("out.gif", save_all=True, append_images=images[1:]) From f7586fc50ce285fe8f7d78683f9397b3089da093 Mon Sep 17 00:00:00 2001 From: jenra Date: Thu, 8 Oct 2020 14:51:00 -0400 Subject: [PATCH 10/17] Added comments --- cellular_automata/conways_game_of_life.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/cellular_automata/conways_game_of_life.py b/cellular_automata/conways_game_of_life.py index ac6c546ff1b2..01bb642f9cca 100644 --- a/cellular_automata/conways_game_of_life.py +++ b/cellular_automata/conways_game_of_life.py @@ -28,6 +28,7 @@ def new_generation(cells: list[list[int]]) -> list[list[int]]: """ + Generates the next generation for a given state of Conway's Game of Life. >>> new_generation(GLIDER) [[0, 0, 0, 0, 0, 0, 0, 0], [1, 0, 1, 0, 0, 0, 0, 0], [0, 1, 1, 0, 0, 0, 0, 0], [0, 1, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0]] >>> new_generation(BLINKER) @@ -70,14 +71,22 @@ def new_generation(cells: list[list[int]]) -> list[list[int]]: return next_generation def generate_images(cells: list[list[int]], frames) -> list[Image.Image]: + """ + Generates a list of images + """ images = [] - for i in range(frames): + for _ in range(frames): + # Create output image img = Image.new("RGB", (len(cells[0]), len(cells))) pixels = img.load() + + # Save cells to image for x in range(len(cells)): for y in range(len(cells[0])): colour = 255 - cells[y][x] * 255 pixels[x, y] = (colour, colour, colour) + + # Save image images.append(img) cells = new_generation(cells) return images From f758067b685b8821da6e40afd8418902a46cc702 Mon Sep 17 00:00:00 2001 From: jenra Date: Thu, 8 Oct 2020 14:54:55 -0400 Subject: [PATCH 11/17] Comment --- cellular_automata/conways_game_of_life.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cellular_automata/conways_game_of_life.py b/cellular_automata/conways_game_of_life.py index 01bb642f9cca..31af9fc61f54 100644 --- a/cellular_automata/conways_game_of_life.py +++ b/cellular_automata/conways_game_of_life.py @@ -72,7 +72,7 @@ def new_generation(cells: list[list[int]]) -> list[list[int]]: def generate_images(cells: list[list[int]], frames) -> list[Image.Image]: """ - Generates a list of images + Generates a list of images of subsequent Game of Life states. """ images = [] for _ in range(frames): From f20948109014641038310de08ade7d79ad53f9c0 Mon Sep 17 00:00:00 2001 From: jenra Date: Thu, 8 Oct 2020 14:59:53 -0400 Subject: [PATCH 12/17] Reformatted file --- cellular_automata/conways_game_of_life.py | 147 +++++++++++----------- 1 file changed, 75 insertions(+), 72 deletions(-) diff --git a/cellular_automata/conways_game_of_life.py b/cellular_automata/conways_game_of_life.py index 31af9fc61f54..2e7b0bb4412b 100644 --- a/cellular_automata/conways_game_of_life.py +++ b/cellular_automata/conways_game_of_life.py @@ -9,88 +9,91 @@ # Define glider example GLIDER = [ - [0, 1, 0, 0, 0, 0, 0, 0], - [0, 0, 1, 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, 0, 0, 0], - [0, 0, 0, 0, 0, 0, 0, 0], - [0, 0, 0, 0, 0, 0, 0, 0], - [0, 0, 0, 0, 0, 0, 0, 0] + [0, 1, 0, 0, 0, 0, 0, 0], + [0, 0, 1, 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, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0], ] # Define blinker example -BLINKER = [ - [0, 1, 0], - [0, 1, 0], - [0, 1, 0] -] +BLINKER = [[0, 1, 0], [0, 1, 0], [0, 1, 0]] + def new_generation(cells: list[list[int]]) -> list[list[int]]: - """ - Generates the next generation for a given state of Conway's Game of Life. - >>> new_generation(GLIDER) - [[0, 0, 0, 0, 0, 0, 0, 0], [1, 0, 1, 0, 0, 0, 0, 0], [0, 1, 1, 0, 0, 0, 0, 0], [0, 1, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0]] - >>> new_generation(BLINKER) - [[0, 0, 0], [1, 1, 1], [0, 0, 0]] - """ - next_generation = [] - for i in range(len(cells)): - next_generation_row = [] - for j in range(len(cells[i])): - # Get the number of live neighbours - neighbour_count = 0 - if i > 0 and j > 0: - neighbour_count += cells[i - 1][j - 1] - if i > 0: - neighbour_count += cells[i - 1][j ] - if i > 0 and j < len(cells[i]) - 1: - neighbour_count += cells[i - 1][j + 1] - if j > 0: - neighbour_count += cells[i ][j - 1] - if j < len(cells[i]) - 1: - neighbour_count += cells[i ][j + 1] - if i < len(cells) - 1 and j > 0: - neighbour_count += cells[i + 1][j - 1] - if i < len(cells) - 1: - neighbour_count += cells[i + 1][j ] - if i < len(cells) - 1 and j < len(cells[i]) - 1: - neighbour_count += cells[i + 1][j + 1] + """ + Generates the next generation for a given state of Conway's Game of Life. + >>> new_generation(GLIDER) + [[0, 0, 0, 0, 0, 0, 0, 0], [1, 0, 1, 0, 0, 0, 0, 0], [0, 1, 1, 0, 0, 0, 0, 0], [0, 1, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0]] + >>> new_generation(BLINKER) + [[0, 0, 0], [1, 1, 1], [0, 0, 0]] + """ + next_generation = [] + for i in range(len(cells)): + next_generation_row = [] + for j in range(len(cells[i])): + # Get the number of live neighbours + neighbour_count = 0 + if i > 0 and j > 0: + neighbour_count += cells[i - 1][j - 1] + if i > 0: + neighbour_count += cells[i - 1][j] + if i > 0 and j < len(cells[i]) - 1: + neighbour_count += cells[i - 1][j + 1] + if j > 0: + neighbour_count += cells[i][j - 1] + if j < len(cells[i]) - 1: + neighbour_count += cells[i][j + 1] + if i < len(cells) - 1 and j > 0: + neighbour_count += cells[i + 1][j - 1] + if i < len(cells) - 1: + neighbour_count += cells[i + 1][j] + if i < len(cells) - 1 and j < len(cells[i]) - 1: + neighbour_count += cells[i + 1][j + 1] - # Rules of the game of life (excerpt from Wikipedia): - # 1. Any live cell with two or three live neighbours survives. - # 2. Any dead cell with three live neighbours becomes a live cell. - # 3. All other live cells die in the next generation. Similarly, all other dead cells stay dead. - alive = cells[i][j] == 1 - if (alive and 2 <= neighbour_count <= 3) or not alive and neighbour_count == 3: - next_generation_row.append(1) - else: - next_generation_row.append(0) + # Rules of the game of life (excerpt from Wikipedia): + # 1. Any live cell with two or three live neighbours survives. + # 2. Any dead cell with three live neighbours becomes a live cell. + # 3. All other live cells die in the next generation. Similarly, all other dead cells stay dead. + alive = cells[i][j] == 1 + if ( + (alive and 2 <= neighbour_count <= 3) + or not alive + and neighbour_count == 3 + ): + next_generation_row.append(1) + else: + next_generation_row.append(0) + + next_generation.append(next_generation_row) + return next_generation - next_generation.append(next_generation_row) - return next_generation def generate_images(cells: list[list[int]], frames) -> list[Image.Image]: - """ - Generates a list of images of subsequent Game of Life states. - """ - images = [] - for _ in range(frames): - # Create output image - img = Image.new("RGB", (len(cells[0]), len(cells))) - pixels = img.load() + """ + Generates a list of images of subsequent Game of Life states. + """ + images = [] + for _ in range(frames): + # Create output image + img = Image.new("RGB", (len(cells[0]), len(cells))) + pixels = img.load() + + # Save cells to image + for x in range(len(cells)): + for y in range(len(cells[0])): + colour = 255 - cells[y][x] * 255 + pixels[x, y] = (colour, colour, colour) - # Save cells to image - for x in range(len(cells)): - for y in range(len(cells[0])): - colour = 255 - cells[y][x] * 255 - pixels[x, y] = (colour, colour, colour) + # Save image + images.append(img) + cells = new_generation(cells) + return images - # Save image - images.append(img) - cells = new_generation(cells) - return images if __name__ == "__main__": - images = generate_images(GLIDER, 16) - images[0].save("out.gif", save_all=True, append_images=images[1:]) + images = generate_images(GLIDER, 16) + images[0].save("out.gif", save_all=True, append_images=images[1:]) From cb7a4db6c9573ad8f63c18d9aa2fd3cc2c228b95 Mon Sep 17 00:00:00 2001 From: jenra Date: Thu, 8 Oct 2020 15:04:29 -0400 Subject: [PATCH 13/17] Formatting --- cellular_automata/conways_game_of_life.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cellular_automata/conways_game_of_life.py b/cellular_automata/conways_game_of_life.py index 2e7b0bb4412b..8d2cb0d454f4 100644 --- a/cellular_automata/conways_game_of_life.py +++ b/cellular_automata/conways_game_of_life.py @@ -57,7 +57,8 @@ def new_generation(cells: list[list[int]]) -> list[list[int]]: # Rules of the game of life (excerpt from Wikipedia): # 1. Any live cell with two or three live neighbours survives. # 2. Any dead cell with three live neighbours becomes a live cell. - # 3. All other live cells die in the next generation. Similarly, all other dead cells stay dead. + # 3. All other live cells die in the next generation. + # Similarly, all other dead cells stay dead. alive = cells[i][j] == 1 if ( (alive and 2 <= neighbour_count <= 3) From 30829c8e987cb37a44ac1d6aa5e69e10bedd10b8 Mon Sep 17 00:00:00 2001 From: jenra Date: Tue, 20 Oct 2020 09:07:36 -0400 Subject: [PATCH 14/17] Removed glider test --- cellular_automata/conways_game_of_life.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/cellular_automata/conways_game_of_life.py b/cellular_automata/conways_game_of_life.py index 8d2cb0d454f4..3e967cfa03ed 100644 --- a/cellular_automata/conways_game_of_life.py +++ b/cellular_automata/conways_game_of_life.py @@ -26,8 +26,6 @@ def new_generation(cells: list[list[int]]) -> list[list[int]]: """ Generates the next generation for a given state of Conway's Game of Life. - >>> new_generation(GLIDER) - [[0, 0, 0, 0, 0, 0, 0, 0], [1, 0, 1, 0, 0, 0, 0, 0], [0, 1, 1, 0, 0, 0, 0, 0], [0, 1, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0]] >>> new_generation(BLINKER) [[0, 0, 0], [1, 1, 1], [0, 0, 0]] """ From 93ae2369c1f1db64fc01564eb3735e3a9e95b136 Mon Sep 17 00:00:00 2001 From: jenra Date: Fri, 23 Oct 2020 16:27:48 -0400 Subject: [PATCH 15/17] Update cellular_automata/conways_game_of_life.py Co-authored-by: John Law --- cellular_automata/conways_game_of_life.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cellular_automata/conways_game_of_life.py b/cellular_automata/conways_game_of_life.py index 3e967cfa03ed..d2380b6bbcf7 100644 --- a/cellular_automata/conways_game_of_life.py +++ b/cellular_automata/conways_game_of_life.py @@ -23,7 +23,7 @@ BLINKER = [[0, 1, 0], [0, 1, 0], [0, 1, 0]] -def new_generation(cells: list[list[int]]) -> list[list[int]]: +def new_generation(cells: List[List[int]]) -> List[List[int]]: """ Generates the next generation for a given state of Conway's Game of Life. >>> new_generation(BLINKER) From 866054773fa19e16f9a49e144828c026c1e1a5cf Mon Sep 17 00:00:00 2001 From: John Law Date: Sun, 29 Nov 2020 23:37:48 +0800 Subject: [PATCH 16/17] Update conways_game_of_life.py --- cellular_automata/conways_game_of_life.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cellular_automata/conways_game_of_life.py b/cellular_automata/conways_game_of_life.py index d2380b6bbcf7..a665ae641245 100644 --- a/cellular_automata/conways_game_of_life.py +++ b/cellular_automata/conways_game_of_life.py @@ -4,7 +4,7 @@ """ from __future__ import annotations - +from typing import List from PIL import Image # Define glider example From cff3f915f5ab884d90c05f3121ecfb9eeae8d7d9 Mon Sep 17 00:00:00 2001 From: John Law Date: Mon, 30 Nov 2020 00:03:35 +0800 Subject: [PATCH 17/17] Update conways_game_of_life.py --- cellular_automata/conways_game_of_life.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cellular_automata/conways_game_of_life.py b/cellular_automata/conways_game_of_life.py index a665ae641245..321baa3a3794 100644 --- a/cellular_automata/conways_game_of_life.py +++ b/cellular_automata/conways_game_of_life.py @@ -4,7 +4,9 @@ """ from __future__ import annotations + from typing import List + from PIL import Image # Define glider example