annotate ch6ex2_4.py @ 43:6cd37534c12e

Chapter 6, exercise 3: exploring rule 110 cellular automata.
author Brian Neal <bgneal@gmail.com>
date Mon, 14 Jan 2013 20:41:41 -0600
parents 039249efe42f
children
rev   line source
bgneal@42 1 """Chapter 6, exercise 2 in Allen Downey's Think Complexity book.
bgneal@42 2
bgneal@42 3 4. Implement a Rule 30 CA on a ring with a few hundred cells, run it for as many
bgneal@42 4 time steps as you can in a reasonable amount of time, and output the center
bgneal@42 5 column as a sequence of bits. Test it using DieHarder.
bgneal@42 6
bgneal@42 7 We'll take a slightly different tact. We will create a program that will
bgneal@42 8 continually output the center column as a bit stream. Once we reach the end of
bgneal@42 9 the time steps, we'll copy the last row to row 0 and start again. This way we
bgneal@42 10 can feed the data into dieharder over a pipe without it exhausting our stream.
bgneal@42 11
bgneal@42 12 """
bgneal@42 13 import sys
bgneal@42 14
bgneal@42 15 from CircularCA import CircularCA
bgneal@42 16
bgneal@42 17
bgneal@42 18 def main(script, bytes_wanted):
bgneal@42 19
bgneal@42 20 bytes_wanted = int(bytes_wanted)
bgneal@42 21
bgneal@42 22 # Create a circular CA that is 257 columns; it is odd so that we have a true
bgneal@42 23 # "center" column. Our CA will have 8192 steps. This will give us 8192
bgneal@42 24 # / 8 == 1024 bytes of pseudo-random (we hope) data using rule 30. Once
bgneal@42 25 # we've reached the end of the time steps, we'll copy the last row to the
bgneal@42 26 # first and start over.
bgneal@42 27
bgneal@42 28 rows = 8193
bgneal@42 29 cols = 257
bgneal@42 30 mid = cols // 2
bgneal@42 31 ca = CircularCA(30, rows, cols)
bgneal@42 32 ca.start_single()
bgneal@42 33
bgneal@42 34 iters = 0
bgneal@42 35 bytes_produced = 0
bgneal@42 36 while True:
bgneal@42 37 ca.loop(rows - 1)
bgneal@42 38
bgneal@42 39 iters += 1
bgneal@42 40 if iters == 1:
bgneal@42 41 # don't use the first iteration as the first few rows will have 0's
bgneal@42 42 # until it fills up
bgneal@42 43 ca.wrap()
bgneal@42 44 continue
bgneal@42 45
bgneal@42 46 a = ca.get_array(mid, mid + 1)
bgneal@42 47
bgneal@42 48 # output the bit stream a byte at a time
bgneal@42 49 x = 0
bgneal@42 50 i = 0
bgneal@42 51 for n, item in enumerate(a):
bgneal@42 52 # don't use the first bit because it is a repeat from the previous
bgneal@42 53 # iteration
bgneal@42 54 if n == 0:
bgneal@42 55 continue
bgneal@42 56
bgneal@42 57 x <<= 1
bgneal@42 58 x |= item[0]
bgneal@42 59 i += 1
bgneal@42 60 if i == 8:
bgneal@42 61 sys.stdout.write(chr(x))
bgneal@42 62 x = 0
bgneal@42 63 i = 0
bgneal@42 64 bytes_produced += 1
bgneal@42 65 if bytes_produced >= bytes_wanted:
bgneal@42 66 return # we're done
bgneal@42 67
bgneal@42 68 # now start the CA over:
bgneal@42 69 ca.wrap()
bgneal@42 70
bgneal@42 71
bgneal@42 72 if __name__ == '__main__':
bgneal@42 73 main(*sys.argv)