Add files via upload

This commit is contained in:
Peter Norvig authored and GitHub committed 2020-04-14 23:46:10 -07:00
1 parent 72273bcb88
commit 5de6713d8b
1 file changed
+136 -125
+136 -125
View File
@@ -4,21 +4,21 @@
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {}, "metadata": {},
"source": [ "source": [
"<div style=\"text-align: right\">Peter Norvig<br>13 March 2018</div> \n", "<div align=\"right\" style=\"text-align: right\"><i>Peter Norvig<br>March 2018</i></div> \n",
"\n", "\n",
"# Maze Generation\n", "# Maze Generation\n",
"\n", "\n",
"Let's make some mazes! I'm thinking of mazes like this one, which is a rectangular grid of squares, with walls on some of the sides of squares, and openings on other sides:\n", "Let's make some mazes! I'm thinking of mazes like this one, which is a rectangular grid of squares, with walls on some of the sides of squares, and openings on other sides. The goal is to get from the red arrow to the green arrow.\n",
"\n", "\n",
"![Wikipedia](https://upload.wikimedia.org/wikipedia/commons/thumb/8/88/Maze_simple.svg/475px-Maze_simple.svg.png)\n", "![Wikipedia](https://upload.wikimedia.org/wikipedia/commons/thumb/8/88/Maze_simple.svg/475px-Maze_simple.svg.png)\n",
"\n", "\n",
"The main constraint is that there should be a path from entrance to exit, and it should be ***fun*** to solve the maze with pencil, paper, and brain power&mdash;not too easy, but also not impossible. \n", "The two main constraints are that there should be a path from entrance to exit, and it should be ***fun*** to solve the maze with pencil, paper, and brain power&mdash;not too easy, but also not impossible. \n",
"\n", "\n",
"As I think about how to model a maze on the computer, it seems like a **graph** is the right model: the nodes of\n", "As I think about how to model a maze on the computer, it seems like a **graph** is the right model: the nodes of\n",
"the graph are the squares of the grid, and the edges of the graph are the openings between adjacent squares. So what properties of a graph make a good maze?\n", "the graph are the squares of the grid, and the edges of the graph are the openings between adjacent squares. So what properties of a graph make a good maze?\n",
"- There must be a path from entrance to exit.\n", "- There must be a path from entrance to exit.\n",
"- There must not be too such many paths; maybe it is best if there is only one. \n", "- There must not be too many such paths; maybe it is best if there is only one. \n",
"- Probably the graph should be *singly connected*&mdash;there shouldn't be islands of squares that are unreachable from the start. And maybe we want exactly one path between any two squares.\n", "- Probably the graph should be *singly connected*&mdash;there shouldn't be islands of squares that are unreachable from the start. In fact, maybe we want exactly one path between any two squares.\n",
"- The path should have many twists; it would be too easy if it was mostly straight.\n", "- The path should have many twists; it would be too easy if it was mostly straight.\n",
"\n", "\n",
"I know that a **tree** has all these properties except the last one. So my goal has become: *Superimpose a tree over the grid, covering every square, and make sure the paths are twisty.* Here's how I'll do it:\n", "I know that a **tree** has all these properties except the last one. So my goal has become: *Superimpose a tree over the grid, covering every square, and make sure the paths are twisty.* Here's how I'll do it:\n",
@@ -51,7 +51,7 @@
" o o--o--o--o--o--o--o--o--o--o\n", " o o--o--o--o--o--o--o--o--o--o\n",
" | A b c| | | | | | | |\n", " | A b c| | | | | | | |\n",
" o o--o o--o--o--o--o--o--o--o\n", " o o--o o--o--o--o--o--o--o--o\n",
" | B| e d| | N| | | | | |\n", " | B| e| d| | N| | | | | |\n",
" o o--o--o--o o--o--o--o--o--o\n", " o o--o--o--o o--o--o--o--o--o\n",
" | C D| | | M| | | | | |\n", " | C D| | | M| | | | | |\n",
" o--o o--o--o o--o--o--o--o--o\n", " o--o o--o--o o--o--o--o--o--o\n",
@@ -63,21 +63,25 @@
"Continue like this until every square in the grid has been added to the tree. \n", "Continue like this until every square in the grid has been added to the tree. \n",
"\n", "\n",
"\n", "\n",
"## Implementing Random Trees\n", "# Implementing Random Trees\n",
"\n", "\n",
"I'll make the following implementation choices:\n", "I'll make the following implementation choices:\n",
"\n", "\n",
"- A tree will be represented as a list of edges.\n", "- A tree will be represented as a list of edges.\n",
"- An `Edge` is a tuple of two nodes. I'll keep them sorted so that `Edge(A, B)` is the same as `Edge(B, A)`.\n", "- An `Edge` is a tuple of two nodes. Edges are bidirectional, so to avoid confusion we will always us the tuple that is in sorted order: always `(1, 2)`, never `(2, 1)`. The constructor `edge` enforces that.\n",
"- A node in a tree can be anything: a number, a letter, a square, ...\n", "- A node in a tree can be anything: a number, a letter, a square, ...\n",
"- The algorithm for `random_tree(nodes, neighbors, pop)` is as follows:\n", "- The algorithm for `random_tree(nodes, neighbors, pop)` works as follows:\n",
" * We will keep track of three collections:\n", " * The arguments are:\n",
" - `nodes`: a collection of nodes.\n",
" - `neighbors`: a function such that `neighbors(node)` returns a set of nodes.\n",
" - `pop`: a function such that `pop(frontier)` removes and returns an element from `frontier`.\n",
" * The function keeps track of three collections:\n",
" - `tree`: a list of edges that constitutes the tree.\n", " - `tree`: a list of edges that constitutes the tree.\n",
" - `nodes`: the set of nodes that have not yet been added to the tree, but will be.\n", " - `nodes`: the set of nodes that have not yet been added to the tree, but will be.\n",
" - `frontier`: a queue of nodes in the tree that are eligible to have an edge added.\n", " - `frontier`: a queue of nodes in the tree that are eligible to have an edge added.\n",
" * On each iteration:\n", " * On each iteration:\n",
" - Use `pop` to pick a `node` from the frontier, and find the neighbors that are not already in the tree.\n", " - Use `pop` to pick a `node` from the frontier, and find the neighbors that are not already in the tree.\n",
" - If there are any neighbors, randomly pick one (`nbr`), add `Edge(node, nbr)` to `tree`, remove the\n", " - If there are any neighbors, randomly pick one (`nbr`), add `edge(node, nbr)` to `tree`, remove the\n",
" neighbor from `nodes`, and keep both the node and the neighbor on the frontier. If there are no neighbors,\n", " neighbor from `nodes`, and keep both the node and the neighbor on the frontier. If there are no neighbors,\n",
" drop the node from the frontier.\n", " drop the node from the frontier.\n",
" * When no `nodes` remain, return `tree`." " * When no `nodes` remain, return `tree`."
@@ -86,19 +90,21 @@
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 1, "execution_count": 1,
"metadata": { "metadata": {},
"collapsed": false
},
"outputs": [], "outputs": [],
"source": [ "source": [
"import random\n", "import random\n",
"from collections import deque, namedtuple\n", "from collections import deque, namedtuple\n",
"\n", "\n",
"def Edge(node1, node2): return tuple(sorted([node1, node2]))\n", "Edge = tuple\n",
"Tree = list\n",
"\n", "\n",
"def random_tree(nodes: set, neighbors: callable, pop: callable) -> [Edge]:\n", "def edge(A, B) -> Edge: return Edge(sorted([A, B]))\n",
" \"Repeat: pop a node and add Edge(node, nbr) until all nodes have been added to tree.\"\n", "\n",
" tree = []\n", "def random_tree(nodes, neighbors, pop=deque.pop) -> [Edge]:\n",
" \"\"\"Repeat: pop a node and add edge(node, nbr) until all nodes have been added to tree.\"\"\"\n",
" tree = Tree()\n",
" nodes = set(nodes)\n",
" root = nodes.pop()\n", " root = nodes.pop()\n",
" frontier = deque([root])\n", " frontier = deque([root])\n",
" while nodes:\n", " while nodes:\n",
@@ -106,7 +112,7 @@
" nbrs = neighbors(node) & nodes\n", " nbrs = neighbors(node) & nodes\n",
" if nbrs:\n", " if nbrs:\n",
" nbr = random.choice(list(nbrs))\n", " nbr = random.choice(list(nbrs))\n",
" tree.append(Edge(node, nbr))\n", " tree.append(edge(node, nbr))\n",
" nodes.remove(nbr)\n", " nodes.remove(nbr)\n",
" frontier.extend([node, nbr])\n", " frontier.extend([node, nbr])\n",
" return tree" " return tree"
@@ -116,7 +122,7 @@
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {}, "metadata": {},
"source": [ "source": [
"## Implementing Random Mazes\n", "# Implementing Random Mazes\n",
"\n", "\n",
"Now let's use `random_tree` to implement `random_maze`. Some more choices:\n", "Now let's use `random_tree` to implement `random_maze`. Some more choices:\n",
"\n", "\n",
@@ -128,24 +134,24 @@
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 2, "execution_count": 2,
"metadata": { "metadata": {},
"collapsed": true
},
"outputs": [], "outputs": [],
"source": [ "source": [
"Maze = namedtuple('Maze', 'width, height, edges')\n", "Maze = namedtuple('Maze', 'width, height, edges')\n",
"\n", "\n",
"def neighbors4(square):\n", "Square = tuple\n",
" \"The 4 neighbors of an (x, y) square.\"\n", "\n",
"def neighbors4(square) -> {Square}:\n",
" \"\"\"The 4 neighbors of an (x, y) square.\"\"\"\n",
" (x, y) = square\n", " (x, y) = square\n",
" return {(x + 1, y), (x - 1, y), (x, y + 1), (x, y - 1)}\n", " return {(x + 1, y), (x - 1, y), (x, y + 1), (x, y - 1)}\n",
"\n", "\n",
"def squares(width, height): \n", "def squares(width, height) -> {Square}: \n",
" \"All squares in a grid of these dimensions.\"\n", " \"\"\"All squares in a grid of these dimensions.\"\"\"\n",
" return {(x, y) for x in range(width) for y in range(height)}\n", " return {(x, y) for x in range(width) for y in range(height)}\n",
"\n", "\n",
"def random_maze(width, height, pop=deque.pop):\n", "def random_maze(width, height, pop=deque.pop) -> Maze:\n",
" \"Use random_tree to generate a random maze.\"\n", " \"\"\"Generate a random maze, using rrandom_tree.\"\"\"\n",
" nodes = squares(width, height)\n", " nodes = squares(width, height)\n",
" tree = random_tree(nodes, neighbors4, pop)\n", " tree = random_tree(nodes, neighbors4, pop)\n",
" return Maze(width, height, tree)" " return Maze(width, height, tree)"
@@ -154,14 +160,12 @@
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 3, "execution_count": 3,
"metadata": { "metadata": {},
"collapsed": false
},
"outputs": [ "outputs": [
{ {
"data": { "data": {
"text/plain": [ "text/plain": [
"Maze(width=10, height=5, edges=[((6, 3), (7, 3)), ((6, 3), (6, 4)), ((6, 4), (7, 4)), ((7, 4), (8, 4)), ((8, 3), (8, 4)), ((8, 2), (8, 3)), ((7, 2), (8, 2)), ((7, 1), (7, 2)), ((7, 0), (7, 1)), ((7, 0), (8, 0)), ((8, 0), (8, 1)), ((8, 1), (9, 1)), ((9, 0), (9, 1)), ((9, 1), (9, 2)), ((9, 2), (9, 3)), ((9, 3), (9, 4)), ((6, 0), (7, 0)), ((5, 0), (6, 0)), ((5, 0), (5, 1)), ((5, 1), (6, 1)), ((6, 1), (6, 2)), ((5, 2), (6, 2)), ((4, 2), (5, 2)), ((3, 2), (4, 2)), ((3, 2), (3, 3)), ((2, 3), (3, 3)), ((2, 2), (2, 3)), ((2, 1), (2, 2)), ((2, 0), (2, 1)), ((1, 0), (2, 0)), ((0, 0), (1, 0)), ((0, 0), (0, 1)), ((0, 1), (1, 1)), ((1, 1), (1, 2)), ((0, 2), (1, 2)), ((0, 2), (0, 3)), ((0, 3), (1, 3)), ((1, 3), (1, 4)), ((0, 4), (1, 4)), ((1, 4), (2, 4)), ((2, 4), (3, 4)), ((3, 4), (4, 4)), ((4, 3), (4, 4)), ((4, 3), (5, 3)), ((5, 3), (5, 4)), ((2, 0), (3, 0)), ((3, 0), (4, 0)), ((4, 0), (4, 1)), ((3, 1), (4, 1))])" "Maze(width=10, height=5, edges=[((6, 3), (7, 3)), ((6, 3), (6, 4)), ((5, 4), (6, 4)), ((4, 4), (5, 4)), ((4, 3), (4, 4)), ((3, 3), (4, 3)), ((2, 3), (3, 3)), ((1, 3), (2, 3)), ((0, 3), (1, 3)), ((0, 2), (0, 3)), ((0, 1), (0, 2)), ((0, 0), (0, 1)), ((0, 0), (1, 0)), ((1, 0), (1, 1)), ((1, 1), (2, 1)), ((2, 1), (3, 1)), ((3, 1), (3, 2)), ((2, 2), (3, 2)), ((1, 2), (2, 2)), ((3, 2), (4, 2)), ((4, 2), (5, 2)), ((5, 2), (5, 3)), ((5, 2), (6, 2)), ((6, 2), (7, 2)), ((7, 1), (7, 2)), ((6, 1), (7, 1)), ((5, 1), (6, 1)), ((4, 1), (5, 1)), ((4, 0), (4, 1)), ((4, 0), (5, 0)), ((5, 0), (6, 0)), ((6, 0), (7, 0)), ((7, 0), (8, 0)), ((8, 0), (9, 0)), ((9, 0), (9, 1)), ((9, 1), (9, 2)), ((9, 2), (9, 3)), ((9, 3), (9, 4)), ((8, 4), (9, 4)), ((8, 3), (8, 4)), ((8, 2), (8, 3)), ((8, 1), (8, 2)), ((7, 4), (8, 4)), ((3, 0), (4, 0)), ((2, 0), (3, 0)), ((0, 3), (0, 4)), ((0, 4), (1, 4)), ((1, 4), (2, 4)), ((2, 4), (3, 4))])"
] ]
}, },
"execution_count": 3, "execution_count": 3,
@@ -179,44 +183,44 @@
"source": [ "source": [
"That's not very pretty to look at. I'm going to need a way to visualize a maze.\n", "That's not very pretty to look at. I'm going to need a way to visualize a maze.\n",
"\n", "\n",
"# Printing a maze" "# Printing a maze\n",
"\n",
"Here's a function to print a maze:"
] ]
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 4, "execution_count": 4,
"metadata": { "metadata": {},
"collapsed": false
},
"outputs": [ "outputs": [
{ {
"name": "stdout", "name": "stdout",
"output_type": "stream", "output_type": "stream",
"text": [ "text": [
"o o--o--o--o--o--o--o--o--o--o\n", "o o--o--o--o--o--o--o--o--o--o\n",
"| | | |\n", "| | | |\n",
"o--o--o--o o--o o o o--o o\n", "o--o--o--o o o--o o o--o o\n",
"| | | | |\n", "| | | | | | |\n",
"o o o--o--o o--o--o--o--o o\n", "o o o o--o--o o o--o o o\n",
"| | | | | | |\n", "| | | | | |\n",
"o o--o o o--o o o--o o--o\n", "o o--o o o--o--o--o--o--o o\n",
"| | | | | | |\n", "| | | | | | |\n",
"o o o--o--o--o--o o o--o o\n", "o o o--o--o--o o o o o o\n",
"| | |\n", "| | | | |\n",
"o--o--o--o--o--o--o--o--o--o o\n" "o--o--o--o--o--o--o--o--o--o o\n"
] ]
} }
], ],
"source": [ "source": [
"def print_maze(maze, dot='o', lin='--', bar='|', sp=' '):\n", "def print_maze(maze, dot='o', bar='|', sp1=' ', sp2=' ', lin='--'):\n",
" \"Print maze in ASCII.\"\n", " \"\"\"Print maze in ASCII.\"\"\"\n",
" exit = Edge((maze.width-1, maze.height-1), (maze.width-1, maze.height))\n", " exit = edge((maze.width-1, maze.height-1), (maze.width-1, maze.height))\n",
" edges = set(maze.edges) | {exit}\n", " edges = set(maze.edges) | {exit}\n",
" print(dot + sp + lin.join(dot * maze.width)) # Top line, including entrance\n", " print(dot + sp2 + lin.join(dot * maze.width)) # Top line, including entrance\n",
" def vert_wall(x, y): return (' ' if Edge((x, y), (x+1, y)) in edges else bar)\n", " def vert_wall(x, y): return (sp1 if edge((x, y), (x+1, y)) in edges else bar)\n",
" def horz_wall(x, y): return (sp if Edge((x, y), (x, y+1)) in edges else lin)\n", " def horz_wall(x, y): return (sp2 if edge((x, y), (x, y+1)) in edges else lin)\n",
" for y in range(maze.height):\n", " for y in range(maze.height):\n",
" print(bar + cat(sp + vert_wall(x, y) for x in range(maze.width)))\n", " print(bar + cat(sp2 + vert_wall(x, y) for x in range(maze.width)))\n",
" print(dot + cat(horz_wall(x, y) + dot for x in range(maze.width)))\n", " print(dot + cat(horz_wall(x, y) + dot for x in range(maze.width)))\n",
" \n", " \n",
"cat = ''.join\n", "cat = ''.join\n",
@@ -238,30 +242,28 @@
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 5, "execution_count": 5,
"metadata": { "metadata": {},
"collapsed": false
},
"outputs": [], "outputs": [],
"source": [ "source": [
"%matplotlib inline\n", "%matplotlib inline\n",
"import matplotlib.pyplot as plt\n", "import matplotlib.pyplot as plt\n",
"\n", "\n",
"def plot_maze(maze):\n", "def plot_maze(maze, figsize=None):\n",
" \"Plot a maze by drawing lines between adjacent squares, except for pairs in maze.edges\"\n", " \"\"\"Plot a maze by drawing lines between adjacent squares, except for pairs in maze.edges\"\"\"\n",
" plt.figure(figsize=(8, 4))\n", " w, h = maze.width, maze.height\n",
" plt.figure(figsize=figsize or (w/5, h/5))\n",
" plt.axis('off')\n", " plt.axis('off')\n",
" plt.gca().invert_yaxis()\n", " plt.gca().invert_yaxis()\n",
" w, h = maze.width, maze.height\n", " exits = {edge((0, 0), (0, -1)), edge((w-1, h-1), (w-1, h))}\n",
" exits = {Edge((0, 0), (0, -1)), Edge((w-1, h-1), (w-1, h))}\n",
" edges = set(maze.edges) | exits\n", " edges = set(maze.edges) | exits\n",
" for sq in squares(w, h):\n", " for sq in squares(w, h):\n",
" for nbr in neighbors4(sq):\n", " for nbr in neighbors4(sq):\n",
" if Edge(sq, nbr) not in edges:\n", " if edge(sq, nbr) not in edges:\n",
" plot_wall(sq, nbr)\n", " plot_wall(sq, nbr)\n",
" plt.show()\n", " plt.show()\n",
"\n", "\n",
"def plot_wall(s1, s2):\n", "def plot_wall(s1, s2):\n",
" \"Plot a thick black line between squares s1 and s2.\"\n", " \"\"\"Plot a thick black line between squares s1 and s2.\"\"\"\n",
" (x1, y1), (x2, y2) = s1, s2\n", " (x1, y1), (x2, y2) = s1, s2\n",
" if x1 == x2: # horizontal wall\n", " if x1 == x2: # horizontal wall\n",
" y = max(y1, y2)\n", " y = max(y1, y2)\n",
@@ -269,7 +271,7 @@
" else: # vertical wall\n", " else: # vertical wall\n",
" x = max(x1, x2)\n", " x = max(x1, x2)\n",
" X, Y = [x, x], [y1, y1+1]\n", " X, Y = [x, x], [y1, y1+1]\n",
" plt.plot(X, Y, 'k-', linewidth=4.0)" " plt.plot(X, Y, 'k-', linewidth=3.0)"
] ]
}, },
{ {
@@ -282,18 +284,18 @@
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 6, "execution_count": 6,
"metadata": { "metadata": {},
"collapsed": false
},
"outputs": [ "outputs": [
{ {
"data": { "data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAd0AAAD8CAYAAAAyun5JAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAABNxJREFUeJzt2sFuIjEUAMF4xf//svcaJSsIAdr2UnXj9uSZUct6jDnn\nBwDwen9WDwAA70J0ASAiugAQEV0AiIguAEREFwAiogsAEdEFgIjoAkBEdAEgIroAEBFdAIiILgBE\nRBcAIqILABHRBYCI6AJA5LJ6gGvGGPPz7znnWDXLv3ydD4Cz1F1x0wWAiOgCQER0ASCy9U53d7vt\nmHlfu///AXax+r84broAEBFdAIiILgBERBcAIqILABHRBYCI6AJARHQBICK6ABARXQCIiC4AREQX\nACKiCwAR0QWAiOgCQER0ASAiugAQEV0AiIguAEREFwAiogsAEdEFgIjoAkBEdAEgIroAEBFdAIiI\nLgBERBcAIqILABHRBYCI6AJARHQBICK6ABARXQCIiC4ARC6rBzjZGGOunuFec86xeoavTjvHHc9w\nd6c9Y57Dt/Kdmy4AREQXACKiCwARO90n2nF/ccIubcdz++yEMzzN7s+c3/Gt3OamCwAR0QWAiOgC\nQER0ASAiugAQEV0AiIguAEREFwAiogsAEdEFgIjoAkBEdAEgIroAEBFdAIiILgBERBcAIqILABHR\nBYCI6AJARHQBICK6ABARXQCIiC4AREQXACKiCwAR0QWAiOgCQER0ASAiugAQEV0AiIguAEREFwAi\nogsAEdEFgMhl9QC0xhhz9Qy3zDnH6hl4Le/h75xwblznpgsAEdEFgIjoAkDETvfN7Lin4v14D5/D\nOZ7HTRcAIqILABHRBYCI6AJARHQBICK6ABARXQCIiC4AREQXACKiCwAR0QWAiOgCQER0ASAiugAQ\nEV0AiIguAEREFwAiogsAEdEFgIjoAkBEdAEgIroAEBFdAIiILgBERBcAIqILABHRBYCI6AJARHQB\nICK6ABARXQCIiC4AREQXACKiCwAR0QWAyGX1ADDGmKtnuMdp8/IznuvjnOFtbroAEBFdAIiILgBE\n7HQfMOccq2f4HzjHx9mlPZ/38nE7nuHqb8VNFwAiogsAEdEFgIjoAkBEdAEgIroAEBFdAIiILgBE\nRBcAIqILABHRBYCI6AJARHQBICK6ABARXQCIiC4AREQXACKiCwAR0QWAiOgCQER0ASAiugAQEV0A\niIguAEREFwAiogsAEdEFgIjoAkBEdAEgIroAEBFdAIiILgBERBcAIqILAJHL6gHuMcaYq2e4Zs45\nVs9wy+5neIITnjOP863wCm66ABARXQCIiC4ARI7a6dql3c+ZPe6E3d7uz3n3+T4+zpiR87npAkBE\ndAEgIroAEBFdAIiILgBERBcAIqILABHRBYCI6AJARHQBICK6ABARXQCIiC4AREQXACKiCwAR0QWA\niOgCQER0ASAiugAQEV0AiIguAEREFwAiogsAEdEFgIjoAkBEdAEgIroAEBFdAIiILgBERBcAIqIL\nABHRBYCI6AJARHQBICK6ABC5rB7gHmOMuXoG8B7Cz8w5x+oZduOmCwAR0QWAiOgCQGTMaT0FAAU3\nXQCIiC4AREQXACKiCwAR0QWAiOgCQER0ASAiugAQEV0AiIguAEREFwAiogsAEdEFgIjoAkBEdAEg\nIroAEBFdAIiILgBERBcAIqILABHRBYCI6AJARHQBICK6ABARXQCIiC4AREQXACKiCwAR0QWAiOgC\nQER0ASDyFyUScgM3r2rXAAAAAElFTkSuQmCC\n", "image/png": "iVBORw0KGgoAAAANSUhEUgAAASUAAACWCAYAAACYTp4YAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADh0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uMy4xLjMsIGh0dHA6Ly9tYXRwbG90bGliLm9yZy+AADFEAAACwklEQVR4nO3dUUrDUBBA0Ubc/5bjn/hhKZH05U48ZwG1bfAyI8hs+74/ACo+rn4DAD+JEpAiSkCKKAEpogSkiBKQIkpAiigBKaIEpIgSkCJKQMrnmS+2bdv3P9Lt+76d+dq//Qyg5Yzfe5MSkCJKQMqp69sK71oLr7B63b3Td/cuvq/jzv6TikkJSBElIEWUgBRRAlJECUgRJSBFlIAUUQJSRAlIESUgRZSAFFECUkQJSBElIEWUgBRRAlJECUgRJSBFlIAUUQJSRAlIGXfN5IpjlK5avLb6uUx/Ji7ZPGdSAlJECUgZt76tGkNXrCOTRuojVqwj3JdJCUgRJSBFlIAUUQJSRAlIESUgRZSAFFECUkQJSBElIEWUgBRRAlJECUgRJSBFlIAUUQJSRAlIESUgRZSAFFECUsYdDrjilpUjAkw36eiCSQlIESUgZdz6tsqKdWrSSP3KXdbPu3yOx2PunzdMSkCKKAEpogSkiBKQIkpAiigBKaIEpIgSkCJKQIooASmiBKSIEpAiSkCKKAEpogSkiBKQIkpAiigBKaIEpIgSkCJKQMroayarroG4bPLa6vc//fta4YrDrWcwKQEpogSkjF7f3jmSrlgPJo3UR9z1c53J+vmcSQlIESUgRZSAFFECUkQJSBElIEWUgBRRAlJECUgRJSBFlIAUUQJSRAlIESUgRZSAFFECUkQJSBElIEWUgBRRAlJECUgZfc1kFZcnGu76HO76uf7KpASkiBKQMm59W3Xo0EHFYxzv5CwmJSBFlIAUUQJSRAlIESUgRZSAFFECUkQJSBElIEWUgBRRAlJECUgRJSBFlIAUUQJSRAlIESUgRZSAFFECUkQJSBElIOVt10wc2Pu/PPueSZdgTEpAiigBKdu+m7SBDpMSkCJKQIooASmiBKSIEpAiSkCKKAEpogSkiBKQIkpAyhdya3k/PuCAlAAAAABJRU5ErkJggg==\n",
"text/plain": [ "text/plain": [
"<matplotlib.figure.Figure at 0x10dd4dd68>" "<Figure size 360x180 with 1 Axes>"
] ]
}, },
"metadata": {}, "metadata": {
"needs_background": "light"
},
"output_type": "display_data" "output_type": "display_data"
}, },
{ {
@@ -301,22 +303,23 @@
"output_type": "stream", "output_type": "stream",
"text": [ "text": [
"o o--o--o--o--o--o--o--o--o--o\n", "o o--o--o--o--o--o--o--o--o--o\n",
"| | | | |\n",
"o o--o o o o--o o o o o\n",
"| | | | | | | | |\n",
"o o o--o o o o o o o--o\n",
"| | | | | | |\n",
"o o--o o--o o--o--o--o o o\n",
"| | | | | | |\n",
"o o o--o--o--o o--o--o--o o\n",
"| | |\n", "| | |\n",
"o o--o o--o o o--o--o--o o\n",
"| | | | | | | |\n",
"o o o--o o o o--o o--o o\n",
"| | | | | | | |\n",
"o o o o--o--o o o--o o--o\n",
"| | | | | | |\n",
"o--o o--o--o o o o--o--o o\n",
"| | |\n",
"o--o--o--o--o--o--o--o--o--o o\n" "o--o--o--o--o--o--o--o--o--o o\n"
] ]
} }
], ],
"source": [ "source": [
"M = random_maze(10, 5)\n", "M = random_maze(10, 5)\n",
"plot_maze(M) \n", "\n",
"plot_maze(M, (5, 2.5)) \n",
"print_maze(M)" "print_maze(M)"
] ]
}, },
@@ -328,105 +331,113 @@
"\n", "\n",
"Now I want to compare how the maze varies based on theree different choices for the `pop` parameter. \n", "Now I want to compare how the maze varies based on theree different choices for the `pop` parameter. \n",
"\n", "\n",
"(1) The default is `deque.pop`\n", "# `deque.pop`\n",
"which means that the tree is created **depth-first**; we always select the `node` at the end of the `frontier`, so the tree follows a single branch along a randomly-twisted path until the path doubles back on itself and there are no more neighbors; at that point we select the most recent square for which there are neighbors:" "\n",
"The default pop method means that the tree is created **depth-first**; we always select the `node` at the end of the `frontier`, so the tree follows a single branch along a randomly-twisted path until the path doubles back on itself and there are no more neighbors; at that point we select the most recent square for which there are neighbors. The maze with `deque.pop` looks pretty good. Reminds me of those [cyber brain](https://www.vectorstock.com/royalty-free-vector/cyber-brain-vector-3071965) images:"
] ]
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 7, "execution_count": 13,
"metadata": { "metadata": {},
"collapsed": false
},
"outputs": [ "outputs": [
{ {
"data": { "data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAe0AAAD8CAYAAABaSfxxAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAACnJJREFUeJzt3dFu4zYQBVCl6P//cvoUYLGwU1oiOXOlc94KdCVKlnJB\nzHj89f39fQAA/f1TvQAAYIzQBoAQQhsAQghtAAghtAEghNAGgBBCGwBCCG0ACCG0ASCE0AaAEEIb\nAEIIbQAIIbQBIITQBoAQQhsAQghtAAghtAEgxL/VC1jp6+vr+8///v7+/hr5/wBgxLtcWcVOGwBC\nCG0ACCG0ASDErWvao2bXJM7W0nfXRiqsuObu93H2+iqvt/u9rnSn9z5hjSN2/L3ZzU4bAEIIbQAI\nIbQBIITQBoAQQhsAQugeP853A1Z27Y6aPQVu11S5xK7P2V3hM1Q925X3uvvnPGrHRMfUz/ns34dP\n1tu1Y95OGwBCCG0ACCG0ASCEmvYLV2sZK2ohK2o2Z45fdbwV5+pWz6usy40es+peX7Hrc666xk/O\nW/XMjuq+vg7stAEghNAGgBBCGwBCCG0ACCG0ASCE7vEX7tQVPGrXb8SePc/O37Ct+i3hTlOeuj8P\nK87R7dsEZ4+/4nnt3tW94t537Ty30waAEEIbAEIIbQAIoaZ99KmvJEwRe6f71Kjj6F+XW3He7r/y\nlfA8VE2B69R/0K3ef/bedK1Tf8JOGwBCCG0ACCG0ASCE0AaAEEIbAELoHj8yur27TBLr1NH6Tpdv\nA6w6XuIUsYTn4U5T4HZZ3Z1d+Rx27TS30waAEEIbAEIIbQAIoaZ99Kt5vVI1AWh1Talr3ehPVb/y\nNWrF+nZN81qhahrbnd6VLu/lu3Ws+IxTeg3stAEghNAGgBBCGwBCCG0ACCG0ASCE7vGjT9fgzmk9\n3aZ8rT7eCp26vd954ufyt+5TAWe/y5Ud01XPx5O6ye20ASCE0AaAEEIbAEKoab+wq+bYqb6yawJW\n1bSqHefuMkXqN7PXmHDNVyX0LpxVWU+/ovJXvapr3XbaABBCaANACKENACGENgCEENoAEOJR3eNX\nu/7OdkpWdxuOuNpZvfre/Ha8s/d31+dyp8+/6nh/++R5mP3MXrX63sw4/ux7s/odrewm381OGwBC\nCG0ACCG0ASDEo2raVTWKjrWRqnr8jnvRfcpT8vNQdfyEvoDZk/QqpwfOlvC3N+EZOw47bQCIIbQB\nIITQBoAQQhsAQghtAAjxqO7xd6omau3oVqzqQO3YidllytPo8Sp/U3yXTlMGR49ZdQ+7fXav7Pq2\nScK9WMVOGwBCCG0ACCG0ASCEmvbRZ6LQznV0n3RW9QtMV87V5Tn6Tfdpce8kTNKbrXI9adPYuqxj\nBzttAAghtAEghNAGgBBCGwBCaEQ7+nxRf8U6ug9NmbG+quE4q8+z87nsMnim4zvQ5e/DCpXDbHZI\nXfdv7LQBIITQBoAQQhsAQqhpH8/6Yv5VowP8K+9p98+z+/p+c+fBM+/caXDQ7KEpnd77EZU9NLPY\naQNACKENACGENgCEENoAEEJoA0CIR3WPV3f9VejWzVn5Gaw+950mb81eS6dre6fbtL+z6+nYIT3a\nZd7p70O3v50/7LQBIITQBoAQQhsAQjyqpt2tRpFSQxmRMCkrbcpTZW1y1zV3udcJZtybhPd05nkT\neik+ZacNACGENgCEENoAEEJoA0AIoQ0AIR7VPf7O7A7bFR2L3bsgO03Qmv2bwaPneULHdVU3evfn\n/5XVv8M9Q9XncvVanvytAzttAAghtAEghNAGgBBq2i9crVXvqK90qxGenTZ29XivjtnxF4RGJNbl\nqu71imlxqe/UJ7q897ue9cR36v/YaQNACKENACGENgCEENoAEEJoA0AI3eMXdOxGXt2lueuaEyce\njd6bjs/Nnayezjf7mxJXv1Gx412pmjK4+t8lstMGgBBCGwBCCG0ACKGm/YHV9eGOddvUmvgrs6/l\nTs/D6Lmq7uGV86ZO30p4VxIm341KqYvbaQNACKENACGENgCEENoAEEJoA0AI3eMfONtd2KUTc+e5\nKzvhZ09vmj2x6qorx6t6xjp25naZvnWnd2WX1X+LO7PTBoAQQhsAQghtAAihpn2cr3NcrWFW/hrP\njrXssqs2nXa8SgnT/v62a42d6vup0+J2H78TO20ACCG0ASCE0AaAEEIbAEIIbQAI8aju8TtNg7pL\np+vo8T9Zx9V7s3pSVtX6VrjTtdxp0tlVXabFXdVtPTPYaQNACKENACGENgCEeFRNO3n6T5dpWcl1\nurN21W1nT+b7RJcJZk98vhLMfgeS/xZXs9MGgBBCGwBCCG0ACCG0ASCE0AaAEI/qHn9n9m9Q75jC\n06Wb/Efi5KGra57dEbviHp5d4xOfr8r3eUSXdfxp9po6TWLr2nlupw0AIYQ2AIQQ2gAQQk37yK3z\ndeYefG72c1h57tmf/yfHWz19q6p3oeM7tfqZTZ3EtpKdNgCEENoAEEJoA0AIoQ0AIYQ2AIR4VPf4\n7M7XjhOKurh6r+98byuvrfs7sLM7ffXa7zQtbvTcs685+XlYxU4bAEIIbQAIIbQBIMSjatpX66er\n6zU7p/WsvuZuU6hWSJyQ5x14r9PndEXyddxpKuAqdtoAEEJoA0AIoQ0AIYQ2AIR4VCPaqNmNBpVf\n/O/WXHH2PJXNH93u4Q7d3oEr67l6LT7X7CE6Z8674tyz2GkDQAihDQAhhDYAhFDTPjKH3O8akrF6\n+EXXutEZrmWfJwxhWXGeLp9r8j2sZqcNACGENgCEENoAEEJoA0AIoQ0AIXSPH+snHlVOVFrdTX71\neKPn+e14q+9v1TSvq98QWCFhOljVGqumhq1ex05d7mFndtoAEEJoA0AIoQ0AIdS0X0ieotOtNl1h\ntBbcbSpT4mfSaS0/Eiccdjj+GWkTEyt/cXEWO20ACCG0ASCE0AaAEEIbAEIIbQAIoXv8A6OdkrMn\nYF055qjqjshOVk+imt1NXmn2GivvTernsmM9VVMBZx/vk3/XsVv/OOy0ASCG0AaAEEIbAEKoaR91\nk4yu1Hm61lv+T7d64CtVE7VWr6Ojymljq3sQuv06XKU7TwXczU4bAEIIbQAIIbQBIITQBoAQQhsA\nQugePzI6mkfN7ji9UwfrqO7PQ/f1vTK7k3rF9MBdnctVv+v+6txV502YPtf1b5idNgCEENoAEEJo\nA0AINe0XVkww++Q8O475xF+kOnu/u9W2PlnP2V+m63bNn6hae8I96zLt753Z0+fu9Fz/sNMGgBBC\nGwBCCG0ACCG0ASCE0AaAELrHN1jRWV3V/Z3QTb7r3KvP0/G3hbtcc8K3FUbNvpYV92b2e//EZ3sW\nO20ACCG0ASCE0AaAEGrax/y6ScLUnapa9womYF03ei13uua72vkZdX8ePllfQr/OcdhpA0AMoQ0A\nIYQ2AIQQ2gAQQmgDQIiv7++IITCnVHf5AZCp629022kDQAihDQAhhDYAhLh1TRsA7sROGwBCCG0A\nCCG0ASCE0AaAEEIbAEIIbQAIIbQBIITQBoAQQhsAQghtAAghtAEghNAGgBBCGwBCCG0ACCG0ASCE\n0AaAEEIbAEIIbQAIIbQBIITQBoAQQhsAQghtAAghtAEghNAGgBBCGwBCCG0ACCG0ASCE0AaAEEIb\nAEIIbQAIIbQBIMR/rtNmnUTdzqUAAAAASUVORK5CYII=\n", "image/png": "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 truncated
"text/plain": [ "text/plain": [
"<matplotlib.figure.Figure at 0x1176e5e80>" "<Figure size 1008x1008 with 1 Axes>"
] ]
}, },
"metadata": {}, "metadata": {
"needs_background": "light"
},
"output_type": "display_data" "output_type": "display_data"
} }
], ],
"source": [ "source": [
"plot_maze(random_maze(40, 20, deque.pop))" "plot_maze(random_maze(70, 70, deque.pop))"
] ]
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {}, "metadata": {},
"source": [ "source": [
"The maze with `deque.pop` looks pretty good. Reminds me of those [cyber brain](https://www.vectorstock.com/royalty-free-vector/cyber-brain-vector-3071965) images.\n", "# `deque.popleft`\n",
"\n", "\n",
"(2) An alternative is `queue.popleft`, which creates the maze roughly **breadth-first**&mdash;we start at some root square , add an edge to it, and from then on we always select first a parent edge before we select a child edge. The net result is a design that appears to radiate out in concentric layers from the root (which is chosen by `random_tree` and is not necessarily the top-left square; below it looks like the root is in the upper-left quadrant). " "This creates the maze roughly **breadth-first**&mdash;we start at some root square , add an edge to it, and from then on we always select first a parent edge before we select a child edge. The net result is a design that appears to radiate out in concentric layers from the root (which is chosen by `random_tree` and is not necessarily the top-left square; below it looks like the root is in the lower-right quadrant). The `deque.popleft` maze is interesting as a design, but to me it doesn't work well as a maze. It is too easy to say: follow the path from the start to the center point, then consider the path from the end to the center point, and see how they match up."
] ]
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 8, "execution_count": 14,
"metadata": { "metadata": {},
"collapsed": false
},
"outputs": [ "outputs": [
{ {
"data": { "data": {
"image/png": "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\n", "image/png": "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 truncated
"text/plain": [ "text/plain": [
"<matplotlib.figure.Figure at 0x1176fcf60>" "<Figure size 1008x1008 with 1 Axes>"
] ]
}, },
"metadata": {}, "metadata": {
"needs_background": "light"
},
"output_type": "display_data" "output_type": "display_data"
} }
], ],
"source": [ "source": [
"plot_maze(random_maze(40, 20, deque.popleft))" "plot_maze(random_maze(70, 70, deque.popleft))"
] ]
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {}, "metadata": {},
"source": [ "source": [
"The `deque.popleft` maze is interesting as a design, but to me it doesn't work well as a maze.\n", "# `poprandom`\n",
"\n", "\n",
"(3) We can select a cell at random by shuffling the frontier before popping an element off of it:" "We can select a cell at random by shuffling the frontier before popping an element off of it.\n",
"This is an interesting compromise: it has some structure, but still works nicely as a maze, in my opinion."
] ]
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 9, "execution_count": 16,
"metadata": { "metadata": {},
"collapsed": false "outputs": [],
},
"outputs": [
{
"data": {
"image/png": "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\nxnjoO1WPSQgAAAAASUVORK5CYII=\n",
"text/plain": [
"<matplotlib.figure.Figure at 0x117710550>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [ "source": [
"def poprandom(seq):\n", "def poprandom(seq):\n",
" \"Shuffle a mutable sequence (deque or list) and then pop an element.\"\n", " \"\"\"Select and return a random element; remove it from the sequence.\"\"\"\n",
" random.shuffle(seq)\n", " element = random.choice(seq)\n",
" return seq.pop()\n", " seq.remove(element)\n",
"\n", " return element"
"plot_maze(random_maze(40, 20, poprandom))" ]
},
{
"cell_type": "code",
"execution_count": 17,
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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 truncated
"text/plain": [
"<Figure size 1008x1008 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"plot_maze(random_maze(70, 70, poprandom))"
] ]
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {}, "metadata": {},
"source": [ "source": [
"This is an interesting compromise: it has some structure, but still works nicely as a maze, in my opinion.\n",
"\n",
"What other variations can you come up with to generate interesting mazes?" "What other variations can you come up with to generate interesting mazes?"
] ]
} }
@@ -447,7 +458,7 @@
"name": "python", "name": "python",
"nbconvert_exporter": "python", "nbconvert_exporter": "python",
"pygments_lexer": "ipython3", "pygments_lexer": "ipython3",
"version": "3.6.0" "version": "3.7.7"
} }
}, },
"nbformat": 4, "nbformat": 4,