\n",
"\n",
"# A Chaos Game with Triangles\n",
"\n",
"John D. Cook [proposed](https://www.johndcook.com/blog/2017/07/08/the-chaos-game-and-the-sierpinski-triangle/) an interesting \"game\" from the book *[Chaos and Fractals](https://smile.amazon.com/Chaos-Fractals-New-Frontiers-Science/dp/0387202293)*: start at a vertex of an equilateral triangle. Then move to a new point halfway between the current point and one of the three vertexes of the triangle, chosen at random. Repeat to create *N* points, and plot them. What do you get? \n",
"\n",
"I'll refactor Cook's code a bit and then we'll see:"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"import matplotlib.pyplot as plt\n",
"import random\n",
"\n",
"def random_walk(vertexes, N):\n",
" \"Walk halfway from current point towards a random vertex; repeat for N points.\"\n",
" points = [random.choice(vertexes)]\n",
" for _ in range(N-1):\n",
" points.append(midpoint(points[-1], random.choice(vertexes)))\n",
" return points\n",
"\n",
"def show_walk(vertexes, N=5000):\n",
" \"Walk halfway towards a random vertex for N points; show reults.\"\n",
" Xs, Ys = transpose(random_walk(vertexes, N))\n",
" Xv, Yv = transpose(vertexes)\n",
" plt.plot(Xs, Ys, 'r.')\n",
" plt.plot(Xv, Yv, 'bs', clip_on=False)\n",
" plt.gca().set_aspect('equal')\n",
" plt.gcf().set_size_inches(9, 9)\n",
" plt.axis('off')\n",
" plt.show()\n",
" \n",
"def midpoint(p, q): return ((p[0] + q[0])/2, (p[1] + q[1])/2)\n",
"\n",
"def transpose(matrix): return zip(*matrix)\n",
"\n",
"triangle = ((0, 0), (0.5, (3**0.5)/2), (1, 0))"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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\n",
"text/plain": [
"