Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download

📚 The CoCalc Library - books, templates and other resources

132922 views
License: OTHER
1
""" Code example from Complexity and Computation, a book about
2
exploring complexity science with Python. Available free from
3
4
http://greenteapress.com/complexity
5
6
Copyright 2016 Allen Downey
7
MIT License: http://opensource.org/licenses/MIT
8
"""
9
from __future__ import print_function, division
10
11
import sys
12
13
import numpy as np
14
import matplotlib.pyplot as plt
15
16
from matplotlib.patches import RegularPolygon
17
18
from Cell2D import Cell2DViewer
19
20
"""
21
For animation to work, you might have to install
22
ffmpeg. On Ubuntu and Linux Mint, the following should work.
23
24
sudo add-apt-repository ppa:mc3man/trusty-media
25
sudo apt-get update
26
sudo apt-get install ffmpeg
27
"""
28
29
class Turmite:
30
"""Implements Langton's Ant"""
31
32
# map from orientation to (di, dj)
33
move = {0: (-1, 0), # north
34
1: (0, 1), # east
35
2: (1, 0), # south
36
3: (0, -1)} # west
37
38
def __init__(self, n, m=None):
39
"""Initializes the attributes.
40
41
n: number of rows
42
m: number of columns
43
"""
44
m = n if m is None else m
45
self.n = n
46
self.m = m
47
self.array = np.zeros((n, m), np.uint8)
48
self.loc = (n//2, m//2)
49
self.state = 0
50
51
def step(self):
52
"""Executes one time step."""
53
try:
54
cell = self.array[self.loc]
55
except IndexError:
56
sys.exit()
57
58
# toggle the current cell
59
self.array[self.loc] ^= 1
60
61
if cell:
62
# turn left
63
self.state = (self.state + 3) % 4
64
else:
65
# turn right
66
self.state = (self.state + 1) % 4
67
68
move = self.move[self.state]
69
self.loc = self.loc[0] + move[0], self.loc[1] + move[1]
70
71
72
class TurmiteViewer(Cell2DViewer):
73
"""Generates an animated view of the grid."""
74
75
cmap = plt.get_cmap('Oranges')
76
77
def __init__(self, viewee):
78
Cell2DViewer.__init__(self, viewee)
79
self.viewee = viewee
80
self.arrow = None
81
82
def draw(self, grid=False):
83
"""Updates the display with the state of the grid."""
84
self.draw_array(self.viewee.array)
85
self.draw_arrow()
86
if grid:
87
self.draw_grid()
88
89
def draw_arrow(self):
90
"""Draws the arrow."""
91
center, angle = self.arrow_specs()
92
self.arrow = RegularPolygon(center, 3, color='orange',
93
radius=0.4, orientation=angle)
94
ax = plt.gca()
95
ax.add_patch(self.arrow)
96
97
def arrow_specs(self):
98
"""Computes the center and orientation of the arrow."""
99
a = self.viewee.array
100
n, m = a.shape
101
i, j = self.viewee.loc
102
center = j+0.5, n-i-0.5
103
angle = -np.pi / 2 * self.viewee.state
104
return center, angle
105
106
def animate_func(self, i):
107
"""Draws one frame of the animation."""
108
self.step()
109
110
# update the array
111
a = self.viewee.array
112
self.im.set_array(a)
113
114
# update the arrow
115
center, angle = self.arrow_specs()
116
self.arrow.xy = center
117
self.arrow.orientation = angle
118
119
return (self.im, self.arrow)
120
121
122
def main(script, *args):
123
"""Runs Langton's Ant."""
124
n, m = 70, 80
125
turmite = Turmite(n, m)
126
viewer = TurmiteViewer(turmite)
127
128
# run a few steps and draw the end condition
129
#for i in range(5):
130
# turmite.step()
131
#viewer.draw(grid=True)
132
133
# run a short animation
134
#anim = viewer.animate(frames=5, interval=1000, grid=True)
135
136
anim = viewer.animate(frames=10700, interval=0)
137
plt.subplots_adjust(left=0.01, right=0.99, bottom=0.01, top=0.99)
138
plt.show()
139
140
141
if __name__ == '__main__':
142
main(*sys.argv)
143
144
145
146