Add files via upload

This commit is contained in:
Peter Norvig
2022-11-02 19:47:57 -07:00
committed by GitHub
parent 7ffd9b6f1b
commit 5748221f7b

View File

@@ -4,19 +4,15 @@
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {}, "metadata": {},
"source": [ "source": [
"<div style=\"text-align: right\"><i>Peter Norvig<br>2017 | 2020</i></div>\n", "# John Conway's Game of Life\n",
"\n", "\n",
"# Conway's Game of Life \n", "The cellular automata game *Life*, invented by the mathematician [John Conway](https://en.wikipedia.org/wiki/John_Horton_Conway), makes a fun programming exercise. Let's review the [rules](http://en.wikipedia.org/wiki/Conway%27s_Game_of_Life):\n",
"\n", "\n",
"![](https://upload.wikimedia.org/wikipedia/commons/thumb/4/45/Glider.svg/140px-Glider.svg.png)\n", "The *world* of the Game of Life is an infinite two-dimensional orthogonal grid of *cells*, each of which is in one of two possible states, *live* or *empty*. Each cell has eight *neighbors*, the cells that are horizontally, vertically, or diagonally adjacent. At each step in time, the following rules are applied to create the next *generation*:\n",
"\n", "\n",
"The cellular automata game *Life*, invented by the mathematician [John H. Conway](https://en.wikipedia.org/wiki/John_Horton_Conway), makes a fun programming exercise. Let's review the [rules](http://en.wikipedia.org/wiki/Conway%27s_Game_of_Life):\n", "+ Any live cell with two or three live neighbors lives on to the next generation.\n",
"\n", "+ Any empty cell with exactly three live neighbors becomes a live cell in the next generation.\n",
">The **world** of *Life* is an infinite two-dimensional orthogonal grid of **cells**, each of which is in one of two possible states, **live** or **empty**. Each cell has eight **neighbors**, the cells that are horizontally, vertically, or diagonally adjacent. We go from one generation to the next with these rules:\n", "+ All other cells are empty in the next generation.\n",
">\n",
">+ Any live cell with two or three live neighbors remains live in the next generation.\n",
">+ Any empty cell with exactly three live neighbors becomes live in the next generation.\n",
">+ All other cells are empty in the next generation.\n",
"\n", "\n",
"For example, in the diagram below, \"`@`\" cells are live. In the transition from Generation 0 to 1, the cell marked \"`,`\" becomes empty (dies off) because it has zero live neighbors. In the next transition, a fourth `@` becomes live, because it has 3 live neighbors. All other cells stay the same. \n", "For example, in the diagram below, \"`@`\" cells are live. In the transition from Generation 0 to 1, the cell marked \"`,`\" becomes empty (dies off) because it has zero live neighbors. In the next transition, a fourth `@` becomes live, because it has 3 live neighbors. All other cells stay the same. \n",
"\n", "\n",
@@ -29,25 +25,53 @@
" \n", " \n",
"\n", "\n",
"\n", "\n",
"The world continues to evolve by these rules for as long as you care to observe. *Life* is a zero-player infinite game.\n", "The world continues to evolve by these rules for as long as you care to observe. \n",
"\n", "\n",
"# Developing a Life Program\n", "# Developing a Life Program\n",
"\n", "\n",
"\n", "\n",
"To create a program to play *Life*, go through the inventory of concepts and decide how to implement each one:\n", "To create a program to play Life, start with the vocabulary of concepts:\n",
"\n",
"+ **World**\n",
"+ **Cell**\n",
"+ **Live/Empty**\n",
"+ **Neighbors**\n",
"+ **Next Generation**\n",
"+ **Display**\n",
"+ **Live Neighbor Counts**\n",
"\n",
"and consider how to implement them:\n",
"\n",
"+ **World**: The state of the world must represent which cells are empty and which are live. The tricky part is that the number of cells is infinite, and we can't store an infinite array in a finite computer. I can think of three ways to deal with this problem:\n",
" 1. **Change the rules**; make the world finite instead of infinite. (Cells at the edge of the world have fewer neighbors, or perhaps they wrap around to the other side of the world.)\n",
" 2. Use a **finite rectangular window** that covers all the live cells in the infinite grid. As the world\n",
" evolves, this window may have to grow or shift.\n",
"<br>Example: `world = [[0, 0, 0, 0, 0], [0, 0, 0, 1, 0], [0, 1, 0, 0, 0], [0, 1, 1, 0, 0], [0, 0, 0, 0, 0]]` \n",
"\n",
" 3. Represent a world as a **set of live cells.** This set will grow and shrink in size from one generation to the next, but we don't have to worry about overflowing the edges of an array.\n",
"<br>Example: `world = {(3, 1), (1, 2), (1, 3), (2, 3)}` \n",
"<br>I will go with this choice.\n",
"\n",
"\n",
"+ **Cell**: Each cell will be represented as an (x, y) pair of integer coordinates. <br>Example: `cell = (1, 2)`.\n",
"+ **Live/Empty**: \n",
"A cell is live if it is a member of the set of live cells. \n",
"<br>Example: \"`cell in world`\" is True, given the definition of `cell` and `world` above, so `cell` is live.\n",
"+ **Neighbors**: The cell `(x, y)` has eight neighbors, formed by adding or subtracting 1 from `x` or `y` or both. We can define\n",
"a function `neighbors(cell)` to return this set.\n",
"<br>Example: `neighbors((8, 8)) == [(7, 7), (8, 7), (9, 7), (7, 8), (9, 8), (7, 9), (8, 9), (9, 9)]`\n",
"\n",
"+ **Display**: We will need some way to display the state of the world. Let's defer that for now.\n",
"\n",
"+ **Next Generation**: We can define a function, `next_generation(world)`, that takes a world as input and returns\n",
"a new world with the new set of live cells according to the rules.\n",
"Example: `next_generation({(3, 1), (1, 2), (1, 3), (2, 3)}) == {(1, 2), (1, 3), (2, 3)}`\n",
"\n",
"+ **Live Neighbor Counts**: I need to know how many live neighbors each cell has. This can be represented ass a dict or Counter of `{(x, y): count}`. But which cells need to be the keys of this dict? We can start with the live cells, and also add any cells neighboring the live cells. An easy way to generate this dict is to pass to a `Counter` every neighbor of every live cell. This may feel like we're doing the counting \"backwards.\" Instead of asking \"for each cell, how many live neighbors does it have?\" we are saying \"for each live cell, increment the count of each of its neighbors.\" The two amount to the same thing because *neighbor* is symmetric&mdash;if P is a neighbor of Q, then Q is a neighbor of P. Below we see the neighbor counts for each of the three generations; in each generation the top diagram gives the neighbor counts for the empty cells, and the bottom diagram gives the neighbor counts for the live cells. This is just to make the diagram easier to read; in the code these are combined into one `Counter`. Here are the counts:\n",
"\n",
"\n",
"\n",
"\n", "\n",
"+ **World** and **Cell**: A state of the world must represent which cells are empty and which are live. That looks like a job for a two-dimensional array with values 1 for live and 0 for empty. The tricky part is that the number of cells is infinite, and we can't store an infinite array in a finite computer. I can think of three ways around this issue:\n",
" - Use a **fixed-size two-dimensional array** but change the rules: cells at the edge have fewer neighbors, or they wrap around.\n",
" - Use a **sparse matrix** that can change size, expanding in any direction to contain all the live cells.\n",
" - Use a **set of live cells**, where a **cell** is represented as an (x, y)-coordinate pair. I think this is the easiest choice.\n",
"<br>Example: `world = {(3, 1), (1, 2), (1, 3), (2, 3)}; cell = (1, 2)` \n",
"+ **Live** and **Empty**: A cell is live if it is a member of a world, i.e. if `cell in world` is true. \n",
"+ **Neighbors**: The cell `(x, y)` has eight neighbors, formed by adding or subtracting 1 from `x` or `y` or both.\n",
"<br>Example: `neighbors((1, 2))` → `((0, 1), (1, 1), (2, 1), (0, 2), (2, 2), (0, 3), (1, 3), (2, 3))`\n",
"+ **Next Generation**: The function `next_generation(world)` returns a new world with the new set of live cells according to the rules. <br>Example: `next_generation({(3, 1), (1, 2), (1, 3), (2, 3)})` → `{(1, 2), (1, 3), (2, 3)}`\n",
"+ **Sequence of Generations**: The generator function `life(world, n)` yields `n` generations starting from the given world. \n",
"+ **Display**: We will need some way to display the generations. Let's defer that for now.\n",
"+ **Live Neighbor Counts**: To determine the next generation, we need to know how many live neighbors each cell has. A good way to represent this is a mapping of `{cell: count}`. An easy way to produce this mapping is with a `Counter`, passing it every neighbor of every live cell. This may feel like we're doing the counting \"backwards.\" Instead of asking \"for each cell, how many live neighbors does it have?\" we are saying \"for each live cell, increment the count of each of its neighbors.\" The two amount to the same thing because *neighbor* is symmetric&mdash;if P is a neighbor of Q, then Q is a neighbor of P. Below we see the neighbor counts for each of the three generations of the example above; in each generation the top diagram gives the neighbor counts for the empty cells, and the bottom diagram gives the counts for the live cells. This is just to make the diagram easier to read; in the code the counts are all in one `Counter`. \n",
"\n", "\n",
"\n", "\n",
" . . 1 1 1 . . . . . . . . . .\n", " . . 1 1 1 . . . . . . . . . .\n",
@@ -55,7 +79,9 @@
" 2 @ 4 2 1 2 @ 3 1 . 2 @ @ 2 .\n", " 2 @ 4 2 1 2 @ 3 1 . 2 @ @ 2 .\n",
" 2 @ @ 1 . 2 @ @ 1 . 2 @ @ 2 .\n", " 2 @ @ 1 . 2 @ @ 1 . 2 @ @ 2 .\n",
" 1 2 2 1 . 1 2 2 1 . 1 2 2 1 .\n", " 1 2 2 1 . 1 2 2 1 . 1 2 2 1 .\n",
" \n",
" Gen 0 Gen 1 Gen 2\n", " Gen 0 Gen 1 Gen 2\n",
" \n",
" . . . . . . . . . . . . . . .\n", " . . . . . . . . . . . . . . .\n",
" . . . 0 . . . . , . . . . . .\n", " . . . 0 . . . . , . . . . . .\n",
" . 2 . . . . 2 . . . . 3 3 . .\n", " . 2 . . . . 2 . . . . 3 3 . .\n",
@@ -63,62 +89,35 @@
" . . . . . . . . . . . . . . .\n", " . . . . . . . . . . . . . . .\n",
" \n", " \n",
"\n", "\n",
"Now we're ready to start implementing. First some imports and type declarations:" "Below is the implementation. Note that in `next_generation` the `neighbor_counts(world)` is used two ways so I decided to use two different names for clarity: `neighborhood` is used to iterate over all cells that are either live in the world or neighbor a live cell; and `counts` is used to check if a cell has the right number of neighbors."
] ]
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 4, "execution_count": 1,
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
"from collections import Counter\n", "from collections import Counter\n",
"from typing import Set, Tuple, Dict, Iterator, List\n",
"from itertools import islice\n",
"from IPython.display import clear_output, display_html\n",
"from time import sleep\n",
"import sys\n",
"\n", "\n",
"Cell = Tuple[int, int]\n", "def next_generation(world):\n",
"World = Set[Cell] " " \"The set of live cells in the next generation.\"\n",
] " neighborhood = counts = neighbor_counts(world)\n",
}, " return {cell for cell in neighborhood\n",
{ " if (counts[cell] == 3) \n",
"cell_type": "markdown", " or (counts[cell] == 2 and cell in world)}\n",
"metadata": {},
"source": [
"Now the complete implementation, except for display:"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [],
"source": [
"def life(world, n=sys.maxsize) -> Iterator[World]:\n",
" \"\"\"Yield `n` generations, starting from the given world.\"\"\"\n",
" for g in range(n):\n",
" yield world\n",
" world = next_generation(world)\n",
"\n", "\n",
"def next_generation(world) -> World:\n", "def neighbor_counts(world):\n",
" \"\"\"The set of live cells in the next generation.\"\"\"\n", " \"A {cell: int} counter of the number of live neighbors for each cell that has neighbors.\"\n",
" return {cell for cell, count in neighbor_counts(world).items()\n", " return Counter(nb for cell in world \n",
" if count == 3 or (count == 2 and cell in world)}\n", " for nb in neighbors(cell))\n",
"\n", "\n",
"def neighbor_counts(world) -> Dict[Cell, int]:\n", "def neighbors(cell):\n",
" \"\"\"A Counter of the number of live neighbors for each cell.\"\"\"\n", " \"All 8 adjacent neighbors of cell.\"\n",
" return Counter(xy for cell in world \n",
" for xy in neighbors(cell))\n",
"\n",
"def neighbors(cell) -> List[Cell]:\n",
" \"\"\"All 8 adjacent neighbors of cell.\"\"\"\n",
" (x, y) = cell\n", " (x, y) = cell\n",
" return [(x + dx, y + dy) \n", " return [(x-1, y-1), (x, y-1), (x+1, y-1), \n",
" for dx in (-1, 0, 1) \n", " (x-1, y), (x+1, y), \n",
" for dy in (-1, 0, 1) \n", " (x-1, y+1), (x, y+1), (x+1, y+1)]"
" if not (dx == 0 == dy)]"
] ]
}, },
{ {
@@ -130,7 +129,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 3, "execution_count": 2,
"metadata": {}, "metadata": {},
"outputs": [ "outputs": [
{ {
@@ -139,7 +138,7 @@
"{(1, 2), (1, 3), (2, 3)}" "{(1, 2), (1, 3), (2, 3)}"
] ]
}, },
"execution_count": 3, "execution_count": 2,
"metadata": {}, "metadata": {},
"output_type": "execute_result" "output_type": "execute_result"
} }
@@ -149,6 +148,26 @@
"next_generation(world)" "next_generation(world)"
] ]
}, },
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"{(1, 2), (1, 3), (2, 2), (2, 3)}"
]
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"next_generation(next_generation(world))"
]
},
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 4, "execution_count": 4,
@@ -157,10 +176,7 @@
{ {
"data": { "data": {
"text/plain": [ "text/plain": [
"[{(1, 2), (1, 3), (2, 3), (3, 1)},\n", "[(1, 3), (2, 3), (3, 3), (1, 4), (3, 4), (1, 5), (2, 5), (3, 5)]"
" {(1, 2), (1, 3), (2, 3)},\n",
" {(1, 2), (1, 3), (2, 2), (2, 3)},\n",
" {(1, 2), (1, 3), (2, 2), (2, 3)}]"
] ]
}, },
"execution_count": 4, "execution_count": 4,
@@ -169,7 +185,7 @@
} }
], ],
"source": [ "source": [
"list(life(world, 4))" "neighbors((2, 4))"
] ]
}, },
{ {
@@ -181,23 +197,23 @@
"data": { "data": {
"text/plain": [ "text/plain": [
"Counter({(0, 1): 1,\n", "Counter({(0, 1): 1,\n",
" (0, 2): 2,\n",
" (0, 3): 2,\n",
" (1, 1): 1,\n", " (1, 1): 1,\n",
" (1, 3): 2,\n",
" (2, 1): 2,\n", " (2, 1): 2,\n",
" (0, 2): 2,\n",
" (2, 2): 4,\n", " (2, 2): 4,\n",
" (0, 3): 2,\n",
" (1, 3): 2,\n",
" (2, 3): 2,\n", " (2, 3): 2,\n",
" (2, 0): 1,\n", " (2, 0): 1,\n",
" (3, 0): 1,\n", " (3, 0): 1,\n",
" (3, 2): 2,\n",
" (4, 0): 1,\n", " (4, 0): 1,\n",
" (4, 1): 1,\n", " (4, 1): 1,\n",
" (3, 2): 2,\n",
" (4, 2): 1,\n", " (4, 2): 1,\n",
" (1, 2): 2,\n", " (1, 2): 2,\n",
" (3, 3): 1,\n",
" (1, 4): 2,\n", " (1, 4): 2,\n",
" (2, 4): 2,\n", " (2, 4): 2,\n",
" (3, 3): 1,\n",
" (3, 4): 1,\n", " (3, 4): 1,\n",
" (0, 4): 1})" " (0, 4): 1})"
] ]
@@ -211,24 +227,44 @@
"neighbor_counts(world)" "neighbor_counts(world)"
] ]
}, },
{
"cell_type": "markdown",
"metadata": {},
"source": [
"`run` is a function to play n generations of Life:"
]
},
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 11, "execution_count": 6,
"metadata": {},
"outputs": [],
"source": [
"def run(world, n):\n",
" \"Run the world for n generations. No display; just return the nth generation.\"\n",
" for g in range(n):\n",
" world = next_generation(world)\n",
" return world"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {}, "metadata": {},
"outputs": [ "outputs": [
{ {
"data": { "data": {
"text/plain": [ "text/plain": [
"[(0, 1), (0, 2), (0, 3), (1, 1), (1, 3), (2, 1), (2, 2), (2, 3)]" "{(1, 2), (1, 3), (2, 2), (2, 3)}"
] ]
}, },
"execution_count": 11, "execution_count": 7,
"metadata": {}, "metadata": {},
"output_type": "execute_result" "output_type": "execute_result"
} }
], ],
"source": [ "source": [
"neighbors((1, 2))" "run(world, 100)"
] ]
}, },
{ {
@@ -237,46 +273,28 @@
"source": [ "source": [
"# Display\n", "# Display\n",
"\n", "\n",
"To display a world, we'll specify a rectangular window on the infinite plane with ranges of `Xs` and `Ys` coordinates. The function `picture` returns a string depicting the world within that window:" "Now let's see how to display worlds. We'll consider a rectangular window on the infinite plane, specified as ranges of `Xs` and `Ys` coordinates. The function `picture` turns a world into a string showing what the world looks like:"
] ]
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 7, "execution_count": 8,
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
"import time\n",
"from IPython.display import clear_output, display_html\n",
"\n",
"LIVE = '@'\n", "LIVE = '@'\n",
"EMPTY = '.'\n", "EMPTY = '.'\n",
"PAD = ' '\n", "PAD = ' '\n",
" \n", " \n",
"def picture(world, Xs: range, Ys: range) -> str:\n", "def picture(world, Xs, Ys):\n",
" \"\"\"Return a picture of the world: a grid of characters representing the cells in this window.\"\"\"\n", " \"Return a picture: a grid of characters representing the cells in this window.\"\n",
" def row(y): return PAD.join(LIVE if (x, y) in world else EMPTY for x in Xs)\n", " def row(y): return PAD.join(LIVE if (x, y) in world else EMPTY for x in Xs)\n",
" return '\\n'.join(row(y) for y in Ys)" " return '\\n'.join(row(y) for y in Ys)"
] ]
}, },
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"({(1, 2), (1, 3), (2, 3), (3, 1)}, {(1, 2), (1, 3), (2, 3)})"
]
},
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"g = life(world)\n",
"next(g), next(g)"
]
},
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 9, "execution_count": 9,
@@ -302,9 +320,7 @@
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {}, "metadata": {},
"source": [ "source": [
"# Animated Display\n", "The function `display_run` runs the world for `n` steps, displaying the picture at each step:"
"\n",
"The function `animate_life` displays `n` generations: display `world`, pause for `pause` seconds, then clear the screen and display the next generation."
] ]
}, },
{ {
@@ -313,15 +329,17 @@
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
"def animate_life(world, n=10, Xs=range(10), Ys=range(10), pause=1/5):\n", "def display_run(world, n=10, Xs=range(10), Ys=range(10), pause=0.2):\n",
" \"\"\"Display the evolving world for `n` generations.\"\"\"\n", " \"Step and display the world for the given number of generations.\"\n",
" for g, world in enumerate(life(world, n)):\n", " for g in range(n + 1):\n",
" clear_output(wait=True)\n", " html = ('Generation {}, Population {}\\n{}'\n",
" display_html(pre(f'Generation: {g:2}, Population: {len(world):2}\\n' +\n", " .format(g, len(world), pre(picture(world, Xs, Ys))))\n",
" picture(world, Xs, Ys)), raw=True)\n", " clear_output()\n",
" sleep(pause)\n", " display_html(html, raw=True)\n",
" time.sleep(pause)\n",
" world = next_generation(world)\n",
" \n", " \n",
"def pre(text) -> str: return '<pre>' + text + '</pre>'" "def pre(text): return '<pre>' + text + '</pre>'"
] ]
}, },
{ {
@@ -332,8 +350,8 @@
{ {
"data": { "data": {
"text/html": [ "text/html": [
"<pre>Generation: 3, Population: 4\n", "Generation 5, Population 4\n",
". . . . .\n", "<pre>. . . . .\n",
". . . . .\n", ". . . . .\n",
". @ @ . .\n", ". @ @ . .\n",
". @ @ . .\n", ". @ @ . .\n",
@@ -345,7 +363,7 @@
} }
], ],
"source": [ "source": [
"animate_life(world, 4, range(5), range(5), 1)" "display_run(world, 5, range(5), range(5))"
] ]
}, },
{ {
@@ -354,7 +372,7 @@
"source": [ "source": [
"# Interesting Worlds\n", "# Interesting Worlds\n",
"\n", "\n",
"Now let's take a look at some configurations of cells that *Life* enthusiasts have discovered. It would be tedious to write out a set of `(x, y)` coordinates, so we will define the function `shape` that takes a picture as input and returns a world; `shape` and `picture` are more-or-less inverses. " "Now let's take a look at some initial worlds that *Life* enthusiasts have discovered. It would be tedious to enumerate these with an explicit set of `(x, y)` coordinates, so we will define the function `shape` that takes a picture as input and returns a world; `shape` and `picture` are more-or-less inverses. "
] ]
}, },
{ {
@@ -363,35 +381,34 @@
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
"def shape(picture, dx=3, dy=3) -> World:\n", "def shape(picture, offset=(3, 3)):\n",
" \"\"\"Convert a graphical picture (e.g. '@ @ .\\n. @ @') into a world (set of cells).\"\"\"\n", " \"Convert a graphical picture (e.g. '@ @ .\\n. @ @') into a world (set of cells).\"\n",
" cells = {(x, y) \n", " cells = {(x, y) \n",
" for (y, row) in enumerate(picture.splitlines())\n", " for (y, row) in enumerate(picture.splitlines())\n",
" for (x, c) in enumerate(row.replace(PAD, ''))\n", " for (x, c) in enumerate(row.replace(PAD, ''))\n",
" if c == LIVE}\n", " if c == LIVE}\n",
" return slide(cells, dx, dy)\n", " return move(cells, offset)\n",
"\n", "\n",
"def slide(cells, dx, dy):\n", "def move(cells, offset):\n",
" \"\"\"Translate/slide a set of cells by a (dx, dy) offset.\"\"\"\n", " \"Move/Translate/slide a set of cells by a (dx, dy) displacement/offset.\"\n",
" return {(x + dx, y + dy) for (x, y) in cells}\n", " (dx, dy) = offset\n",
" return {(x+dx, y+dy) for (x, y) in cells}\n",
"\n", "\n",
"blinker = shape(\"@@@\")\n", "blinker = shape(\"@@@\")\n",
"block = shape(\"@@\\n@@\")\n", "block = shape(\"@@\\n@@\")\n",
"beacon = block | slide(block, 2, 2)\n", "beacon = block | move(block, (2, 2))\n",
"toad = shape(\".@@@\\n@@@.\")\n", "toad = shape(\".@@@\\n@@@.\")\n",
"glider = shape(\".@.\\n..@\\n@@@\")\n", "glider = shape(\".@.\\n..@\\n@@@\")\n",
"rpentomino = shape(\".@@\\n@@.\\n.@.\", 36, 20)\n", "rpentomino = shape(\".@@\\n@@.\\n.@.\", (36, 20))\n",
"line = shape(\".@@@@@@@@.@@@@@...@@@......@@@@@@@.@@@@@\", 10, 10)\n", "line = shape(\".@@@@@@@@.@@@@@...@@@......@@@@@@@.@@@@@\", (10, 10))\n",
"growth = shape(\"@@@.@\\n@\\n...@@\\n.@@.@\\n@.@.@\", 15, 20)\n", "growth = shape(\"@@@.@\\n@\\n...@@\\n.@@.@\\n@.@.@\", (10, 10))"
"zoo = (slide(blinker, 5, 25) | slide(glider, 8, 13) | slide(blinker, 20, 25) |\n",
" slide(beacon, 24, 25) | slide(toad, 30, 25) | slide(block, 13, 25) | slide(block, 17, 33))"
] ]
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {}, "metadata": {},
"source": [ "source": [
"Here is how `shape` and `slide` work:" "Here is how `shape` and `move` work:"
] ]
}, },
{ {
@@ -419,29 +436,6 @@
"cell_type": "code", "cell_type": "code",
"execution_count": 14, "execution_count": 14,
"metadata": {}, "metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
". . . . . . .\n",
". . . . . . .\n",
". . . . . . .\n",
". . . @ @ . .\n",
". . . . @ @ .\n",
". . . . . . .\n",
". . . . . . .\n"
]
}
],
"source": [
"print(picture(_, range(7), range(7)))"
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {},
"outputs": [ "outputs": [
{ {
"data": { "data": {
@@ -449,7 +443,7 @@
"{(3, 3), (3, 4), (4, 3), (4, 4)}" "{(3, 3), (3, 4), (4, 3), (4, 4)}"
] ]
}, },
"execution_count": 15, "execution_count": 14,
"metadata": {}, "metadata": {},
"output_type": "execute_result" "output_type": "execute_result"
} }
@@ -460,7 +454,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 16, "execution_count": 15,
"metadata": {}, "metadata": {},
"outputs": [ "outputs": [
{ {
@@ -469,13 +463,13 @@
"{(103, 203), (103, 204), (104, 203), (104, 204)}" "{(103, 203), (103, 204), (104, 203), (104, 204)}"
] ]
}, },
"execution_count": 16, "execution_count": 15,
"metadata": {}, "metadata": {},
"output_type": "execute_result" "output_type": "execute_result"
} }
], ],
"source": [ "source": [
"slide(block, 100, 200)" "move(block, (100, 200))"
] ]
}, },
{ {
@@ -487,18 +481,18 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 17, "execution_count": 16,
"metadata": {}, "metadata": {},
"outputs": [ "outputs": [
{ {
"data": { "data": {
"text/html": [ "text/html": [
"<pre>Generation: 9, Population: 3\n", "Generation 10, Population 3\n",
"<pre>. . . . . . . . . .\n",
". . . . . . . . . .\n", ". . . . . . . . . .\n",
". . . . . . . . . .\n", ". . . . . . . . . .\n",
". . . . @ . . . . .\n", ". . . @ @ @ . . . .\n",
". . . . @ . . . . .\n", ". . . . . . . . . .\n",
". . . . @ . . . . .\n",
". . . . . . . . . .\n", ". . . . . . . . . .\n",
". . . . . . . . . .\n", ". . . . . . . . . .\n",
". . . . . . . . . .\n", ". . . . . . . . . .\n",
@@ -511,24 +505,24 @@
} }
], ],
"source": [ "source": [
"animate_life(blinker)" "display_run(blinker)"
] ]
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 18, "execution_count": 17,
"metadata": {}, "metadata": {},
"outputs": [ "outputs": [
{ {
"data": { "data": {
"text/html": [ "text/html": [
"<pre>Generation: 9, Population: 6\n", "Generation 10, Population 8\n",
". . . . . . . . . .\n", "<pre>. . . . . . . . . .\n",
". . . . . . . . . .\n", ". . . . . . . . . .\n",
". . . . . . . . . .\n", ". . . . . . . . . .\n",
". . . @ @ . . . . .\n", ". . . @ @ . . . . .\n",
". . . @ . . . . . .\n", ". . . @ @ . . . . .\n",
". . . . . . @ . . .\n", ". . . . . @ @ . . .\n",
". . . . . @ @ . . .\n", ". . . . . @ @ . . .\n",
". . . . . . . . . .\n", ". . . . . . . . . .\n",
". . . . . . . . . .\n", ". . . . . . . . . .\n",
@@ -540,24 +534,24 @@
} }
], ],
"source": [ "source": [
"animate_life(beacon)" "display_run(beacon)"
] ]
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 19, "execution_count": 18,
"metadata": {}, "metadata": {},
"outputs": [ "outputs": [
{ {
"data": { "data": {
"text/html": [ "text/html": [
"<pre>Generation: 9, Population: 6\n", "Generation 10, Population 6\n",
"<pre>. . . . . . . . . .\n",
". . . . . . . . . .\n", ". . . . . . . . . .\n",
". . . . . . . . . .\n", ". . . . . . . . . .\n",
". . . . . @ . . . .\n", ". . . . @ @ @ . . .\n",
". . . @ . . @ . . .\n", ". . . @ @ @ . . . .\n",
". . . @ . . @ . . .\n", ". . . . . . . . . .\n",
". . . . @ . . . . .\n",
". . . . . . . . . .\n", ". . . . . . . . . .\n",
". . . . . . . . . .\n", ". . . . . . . . . .\n",
". . . . . . . . . .\n", ". . . . . . . . . .\n",
@@ -569,7 +563,36 @@
} }
], ],
"source": [ "source": [
"animate_life(toad)" "display_run(toad)"
]
},
{
"cell_type": "code",
"execution_count": 19,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"Generation 15, Population 5\n",
"<pre>. . . . . . . . . .\n",
". . . . . . . . . .\n",
". . . . . . . . . .\n",
". . . . . . . . . .\n",
". . . . . . . . . .\n",
". . . . . . . . . .\n",
". . . . . . . . . .\n",
". . . . . . . @ . .\n",
". . . . . . . . @ @\n",
". . . . . . . @ @ .</pre>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"display_run(glider, 15)"
] ]
}, },
{ {
@@ -580,17 +603,47 @@
{ {
"data": { "data": {
"text/html": [ "text/html": [
"<pre>Generation: 19, Population: 5\n", "Generation 130, Population 178\n",
". . . . . . . . . .\n", "<pre>. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\n",
". . . . . . . . . .\n", ". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\n",
". . . . . . . . . .\n", ". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\n",
". . . . . . . . . .\n", ". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\n",
". . . . . . . . . .\n", ". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\n",
". . . . . . . . . .\n", ". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . @ . . . . . . . . . . . . . . .\n",
". . . . . . . . . .\n", ". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . @ @ . . . . . . . . . . . . . @\n",
". . . . . . . . . .\n", ". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . @ . @ . . . . . . . . . . . . . @\n",
". . . . . . . . @ .\n", ". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . @\n",
". . . . . . . . . @</pre>" ". . . . . . . . . . . @ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\n",
". . . . . . . . . @ @ @ @ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . @ @\n",
". . . . . @ . @ @ @ @ . @ @ . . . . . . . . . . . . . . . . . . . . . . @ @ . . . . . . . @ . @\n",
". . . @ @ . . @ @ . . @ @ @ . . . . . . . . . . . . . . . . . . . . . . @ @ . . . . . . . @ . @\n",
". . . . . @ @ @ . . . @ @ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . @ .\n",
". . . . . . . . . . . @ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\n",
". . . . . . . . @ . @ . . . . . . . . . . . . . . . . . . . . . . @ @ . . . . . . . . . . . . .\n",
". . . . . . . . @ @ . . . . . . . . . . . . . . . . . @ . @ . . . @ @ . . . . . . . . . . . . .\n",
". . . . @ @ @ . . @ @ . . . . . . . . . . . . . . . . @ . @ . . . . . . . . . . . . . . . . @ @\n",
". . . . @ @ . . . @ @ . . . . . . . . . . . . . . . . @ . . . . . . . . . . . . . . . . . @ @ @\n",
". . . . @ . . . . . . . . . . . . . . . . . . . . . . . @ . . . . . . . . @ . . . . . . . @ . .\n",
". . . . @ @ . @ . . . . . . . . . . . . . . . . . . . . . . . . . . . @ @ . @ . . . . . . . @ .\n",
". . . . . @ @ @ . . . . . . . . . . . . . . . . . . . . . . . . @ . . . . . . @ . . . . . . . .\n",
". . . . @ . . @ . . . . . . . . . . . . . . . . . . . . . . . @ . . . . . . @ . . . @ @ . . . .\n",
". . . . . @ . . . . . . . . . . . . . . . . . . . . . . . . @ . . . . . @ @ . . . @ . . @ . . .\n",
"@ @ . @ @ @ . . . . . . . . . . . . . . . . . . . . . . . . @ . . @ . . . . . . . @ . . @ . . .\n",
". . @ @ . . . . . . . . . . . . . . . . . . . . . . . . . . @ @ . @ @ @ . . . . . . @ @ . . . .\n",
". . . @ @ . . . . . . . . . . . . . . . . . . . . . . . . . . . @ . . . @ . . . . . . . . . . .\n",
"@ @ . @ @ . . . . . . . . . . @ @ . . . . . . . . . . . . . . . @ . . . . . . . . . . . . . . .\n",
"@ . . @ . . . . . . . . . . . @ @ . . . . . . . . . . . . . . . . . . @ . . . . . . . . . . . .\n",
"@ @ @ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\n",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\n",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\n",
". . . @ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\n",
". . @ @ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\n",
". . @ . @ . @ @ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\n",
". . @ . @ . @ @ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\n",
". . @ . @ @ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\n",
". . @ . @ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\n",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\n",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .</pre>"
] ]
}, },
"metadata": {}, "metadata": {},
@@ -598,7 +651,7 @@
} }
], ],
"source": [ "source": [
"animate_life(glider, 20)" "display_run(rpentomino, 130, range(48), range(40))"
] ]
}, },
{ {
@@ -609,82 +662,23 @@
{ {
"data": { "data": {
"text/html": [ "text/html": [
"<pre>Generation: 129, Population: 163\n", "Generation 160, Population 111\n",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\n", "<pre>. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\n",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\n",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\n",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\n",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\n",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\n",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . @ @ @ . . . . . . . . . . . . . .\n",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . @ . . . . . . . . . . . . @ @\n",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . @ . . . . . . . . . . . . . . .\n",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\n",
". . . . . . . . . . @ @ @ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . @ @\n",
". . . . @ . . . @ @ . . @ . . . . . . . . . . . . . . . . . . . . . . . @ @ . . . . . . . @ . @\n",
". . . . @ . @ @ . . . . @ . . . . . . . . . . . . . . . . . . . . . . . @ @ . . . . . . . @ . @\n",
". . . . @ . . . . . . . @ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . @ .\n",
". . . . . . . @ . . . @ . . . . . . . . . . . . . . . . . . . . . @ . . . . . . . . . . . . . .\n",
". . . . . . . . . . @ . . . . . . . . . . . . . . . . . . . . . . . @ . . . . . . . . . . . . .\n",
". . . . . . . @ . @ . . . . . . . . . . . . . . . . . . @ @ . . . . @ . . . . . . . . . . . . .\n",
". . . . . @ . . . @ @ . . . . . . . . . . . . . . . . @ @ @ . . . @ . . . . . . . . . . . . . .\n",
". . . . @ @ . . . @ . . . . . . . . . . . . . . . . . @ . . . . . . . . . . . . . . . . . @ @ @\n",
". . . . @ . . . . . . . . . . . . . . . . . . . . . . . @ @ . . . . . . . . . . . . . . . @ . .\n",
". . . . . @ . . @ . . . . . . . . . . . . . . . . . . . . . . . . . . . @ @ @ . . . . . . . @ @\n",
". . . . . @ @ @ . . . . . . . . . . . . . . . . . . . . . . . . . @ @ . @ @ @ . . . . . . . . .\n",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . @ @ @ @ @ @ @ . . . @ . . . . .\n",
"@ . . . @ @ @ . . . . . . . . . . . . . . . . . . . . . . . . @ @ @ @ . . . . . . @ . @ @ . . .\n",
"@ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . @ @ . . . . . . . . . . @ @ . . . .\n",
". . @ @ . . . . . . . . . . . . . . . . . . . . . . . . . . . @ . . . . . . . . . . @ . . . . .\n",
". . . @ . . @ @ . . . . . . . . . . . . . . . . . . . . . . . . @ @ @ @ @ . . . . . . . . . . .\n",
"@ . . @ . . . . . . . . . . . @ @ . . . . . . . . . . . . . . . . @ @ @ . . . . . . . . . . . .\n",
"@ @ . @ . . . . . . . . . . . @ @ . . . . . . . . . . . . . . . . . . @ . . . . . . . . . . . .\n",
". @ @ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\n",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\n",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\n",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\n",
". . @ @ @ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\n",
". . @ . . . @ @ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\n",
". . . . @ . @ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\n",
". . @ @ @ @ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\n",
". . @ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\n",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\n",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .</pre>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"animate_life(rpentomino, 130, range(48), range(40))"
]
},
{
"cell_type": "code",
"execution_count": 22,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<pre>Generation: 159, Population: 105\n",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\n",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\n", ". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\n",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . @ . . . . @\n", ". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . @ . . . . @\n",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . @ . @ . . . @\n", ". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . @ . . . @ . @ . . @ .\n",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . @ @ @ . . @ . @ . . @ .\n", ". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . @ @ . @ . . @ . @ @ . @ .\n",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . @ @ . @ . . . @ @ . . . @\n", ". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . @ @ . @ @ . . @ @ . . . @\n",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . @ . . . @ . . . . . . . . .\n", ". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . @ . . . @ . . . . . . . . .\n",
". . . . . . . . . . . . . . . . . . . . . . . . @ . . . . . @ . . . @ . @ @ . . . . . . . . . .\n", ". . . . . . . . . . . . . . . . . . . . . . . . . . . . . @ @ @ @ . @ @ @ @ @ . . . . . . . . .\n",
". . . . . . . . . . . . . . . . . . . . . . . . @ . . . @ @ . @ @ @ . . . @ . . . . . . . . . .\n", ". . . . . . . . . . . . . . . . . . . . . . . @ @ @ . . . @ . . . @ @ . . . . . . . . . . . . .\n",
". . . . . . . . . . . . . . . . . . . . . . . . @ . . . . . . @ @ . . @ @ @ @ . . . . . . . . .\n", ". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . @ @ . . @ . @ . @ . . . . . . . . .\n",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . @ . . . . @ . . . . . . . . .\n", ". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . @ . . . . . @ . . . . . . . .\n",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . @ @ @ @ @ @ . . . . . . . . .\n", ". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . @ @ . @ @ . . @ . . . . . . . @\n",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . @ . . . @ @ . . . . . . . @ .\n", ". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . @ @ . . . . @ . . . . . . @ @ .\n",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . @ . . @ . . . . . . . . @ @ .\n", ". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . @ . . @ . . . . . . . . @ @ .\n",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . @ @ @ . . . . . . . . . @ .\n", ". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . @ @ @ . . . . . . . . @ @ .\n",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . @\n", ". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . @ . . . . . . . . . . . @\n",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\n", ". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\n",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\n", ". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\n",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\n", ". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\n",
@@ -696,9 +690,9 @@
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\n", ". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\n",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\n", ". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\n",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\n", ". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\n",
". . . . . . . . . @ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\n", ". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\n",
". . . . . . . . . @ . . . . . . @ @ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\n", ". . . . . . . . @ @ @ . . . . . @ @ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\n",
". . . . . . . . . @ . . . . . @ . . @ . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\n", ". . . . . . . . . . . . . . . @ . . @ . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\n",
". . . . . . . . . . . . . . . . @ @ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\n", ". . . . . . . . . . . . . . . . @ @ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\n",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\n", ". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\n",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\n", ". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\n",
@@ -716,54 +710,57 @@
} }
], ],
"source": [ "source": [
"animate_life(zoo, 160, range(48), range(40))" "zoo = (move(blinker, (5, 25)) | move(glider, (8, 13)) | move(blinker, (20, 25)) |\n",
" move(beacon, (24, 25)) | move(toad, (30, 25)) | move(block, (13, 25)) | move(block, (17, 33)))\n",
"\n",
"display_run(zoo, 160, range(48), range(40))"
] ]
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 23, "execution_count": 22,
"metadata": {}, "metadata": {},
"outputs": [ "outputs": [
{ {
"data": { "data": {
"text/html": [ "text/html": [
"<pre>Generation: 199, Population: 100\n", "Generation 100, Population 72\n",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\n", "<pre>. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\n",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\n", ". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\n",
". . . . . . . . . @ @ @ . . . . . . . . . . . . . . . . . . . . . . . . . . . .\n", ". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\n",
". . . . . . . @ @ . . @ @ . . . . . . . . . . . . . . . . . . . . . . . . . . .\n", ". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\n",
". . . . . . @ . . @ . @ @ @ . . . @ . . . . . . . . . . . . . . . . . . . . . .\n", ". . . . . . . . . . . . . @ . . . @ @ . . . . . . . . . . . . . . . . . . . . .\n",
". . . . . . @ . @ . . . @ @ @ . @ . . . @ @ . . @ @ . . . . . . . . . . . . . .\n", ". . . . . . . . . . . . @ . @ . . @ . @ . . . . . . . . . . . . . . . . . . . .\n",
". . . . . . @ . . . @ . @ @ @ . . . . . . @ @ . @ @ @ . . . . . . . . . . . . .\n", ". . . . . . . . . . . . . @ . . . @ . . @ . . . . . . . . . . . . . . . . . . .\n",
". . . . . . . @ . . . @ @ @ . . . . . @ . @ . @ . . . @ @ . . . . . . . . . . .\n", ". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\n",
". . . . . . . . @ . . . @ . @ @ . . . . @ . . @ . @ . @ @ . . . . . . . . . . .\n", ". . . . . . . . . . . . @ @ . . . . @ . @ . . . . . . . . . . . . . . . . . . .\n",
". . . . . . . . . . . @ . . . @ . . @ @ . . . @ . @ . @ @ . . . . . . . . . . .\n", ". . . . . . . . . . . @ @ @ @ . . . . . . . . . . . . . . . . . . . . . . . . .\n",
". . . . . . . . . . . . . . . . @ @ @ . . . . . . . . . . . . . . . . . . . . .\n", ". . . . . . . . . . @ @ @ . @ @ . @ @ . . . . . . . . . . . . . . . . . . . . .\n",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\n", ". . . . . . . . . . @ @ . . . @ . @ @ @ . . . . . . . . . . . . . . . . . . . .\n",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\n", ". . . . . . . . . @ @ @ . . . . . @ . . @ . . . . . . . . . . . . . . . . . . .\n",
". . . . . . . . . . . . . . . . . . . . . @ @ . . . . . . . . . . . . . . . . .\n", ". . . . . . . @ @ @ @ @ . @ @ @ @ @ @ @ . . . . . . . . . . . . . . . . . . . .\n",
". . . . . . . @ @ @ . @ @ @ @ @ @ @ @ . . . . . . . . . . . . . . . . . . . . .\n",
". . . . . . . . . . @ @ . @ @ @ @ @ . . . . . . . . . . . . . . . . . . . . . .\n",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\n",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\n",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\n",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\n",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\n",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\n",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\n",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\n",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\n",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\n",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\n",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\n", ". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\n",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\n", ". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\n",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\n", ". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\n",
". . . . . . . . . . . . . . . . . . . . . . . . . . . @ . @ . . . . . . . . . .\n",
". . . . . . . . . . . . . . . . . . . . . . . . . . @ . . @ . . . . . . . . . .\n",
". . . . . . . . . . . . . . . . . . . . . . . @ . . . . . @ . . . . . . . . . .\n",
". . . . . . . . . . . . . . . . . . . . . . @ . @ @ . @ . . . . . . @ @ @ . . .\n",
". . . . . . . . . . . . . . . . . . . . . @ . . . @ @ @ . . . . . @ . . . . . .\n",
". . . . . . . . . . . . . . . . . . . . . . @ . . . @ . . . . . . @ . . @ . . .\n",
". . . . . . . . . . . . . . . . . . . . . . . @ @ @ @ . . . . . . . @ @ . . . .\n",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\n", ". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\n",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\n",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\n",
". . . . . . . . . . . . . . . . . . . . @ @ . . . . . . . . . . . . . . . . . .\n",
". . . . . . . . . . . . . . . . . . . . @ @ . . . . . . . . . . . . . . . . . .\n",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\n", ". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\n",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\n", ". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\n",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\n", ". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\n",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\n", ". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\n",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\n", ". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\n",
". . . . . . . . . . . . . . . . @ @ . . . . . . . . . . . . . . . . . . . . . .\n",
". . . . . . . . . . . . . . . . @ @ . . . . . . . . . . . . . . . . . . . . . .\n",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\n", ". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\n",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\n", ". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\n",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\n", ". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\n",
@@ -775,7 +772,7 @@
} }
], ],
"source": [ "source": [
"animate_life(growth, 200, range(40), range(40))" "display_run(growth, 100, range(40), range(40))"
] ]
}, },
{ {
@@ -791,27 +788,27 @@
"and add these lines:\n", "and add these lines:\n",
"\n", "\n",
" def clear_output(): print(\"\\033[;H\\033[2J\") # ANSI terminal home and clear\n", " def clear_output(): print(\"\\033[;H\\033[2J\") # ANSI terminal home and clear\n",
" def display_html(text, raw=False): print(text) \n",
" def pre(text) -> str: return text\n",
" \n", " \n",
"If you want to create a fancier display using some graphics packagee, be my guest. Let me know what you create.\n", " def display_html(text, raw=False): print(text)\n",
" \n",
" def pre(text): return text\n",
" \n", " \n",
"# Coding Kata\n", "# Coding Kata\n",
"\n", "\n",
"I once attended a [code kata](https://en.wikipedia.org/wiki/Kata_%28programming%29) in which one of the exercises was to write *Life* without using any conditional (e.g. `if`) statements. I did it by using roughly the program shown here, but changing the lone `if` to a `filter` in `next_generation`:" "I once attended a [code kata](https://en.wikipedia.org/wiki/Kata_(programming%29) in which one of the exercises was to write the Game of Life without using any conditional (e.g. `if`) statements. I did it by using roughly the program shown here, but changing the lone `if` to a `filter` in `next_generation`:"
] ]
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 24, "execution_count": 23,
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
"def next_generation(world):\n", "def next_generation(world):\n",
" \"\"\"The set of live cells in the next generation.\"\"\"\n", " \"The set of live cells in the next generation.\"\n",
" counts = neighbor_counts(world)\n", " neighborhood = counts = neighbor_counts(world)\n",
" def live(cell): return counts[cell] == 3 or (counts[cell] == 2 and cell in world)\n", " def good(cell): return counts[cell] == 3 or (counts[cell] == 2 and cell in world)\n",
" return set(filter(live, counts))" " return set(filter(good, neighborhood))"
] ]
} }
], ],
@@ -831,9 +828,9 @@
"name": "python", "name": "python",
"nbconvert_exporter": "python", "nbconvert_exporter": "python",
"pygments_lexer": "ipython3", "pygments_lexer": "ipython3",
"version": "3.7.7" "version": "3.7.6"
} }
}, },
"nbformat": 4, "nbformat": 4,
"nbformat_minor": 1 "nbformat_minor": 4
} }