RosettaCodeData/Task/Wireworld/Python/wireworld.py

71 lines
1.9 KiB
Python

'''
Wireworld implementation.
'''
from io import StringIO
from collections import namedtuple
from pprint import pprint as pp
import copy
WW = namedtuple('WW', 'world, w, h')
head, tail, conductor, empty = allstates = 'Ht. '
infile = StringIO('''\
tH.........
. .
...
. .
Ht.. ......\
''')
def readfile(f):
'''file > initial world configuration'''
world = [row.rstrip('\r\n') for row in f]
height = len(world)
width = max(len(row) for row in world)
# fill right and frame in empty cells
nonrow = [ " %*s " % (-width, "") ]
world = nonrow + \
[ " %*s " % (-width, row) for row in world ] + \
nonrow
world = [list(row) for row in world]
return WW(world, width, height)
def newcell(currentworld, x, y):
istate = currentworld[y][x]
assert istate in allstates, 'Wireworld cell set to unknown value "%s"' % istate
if istate == head:
ostate = tail
elif istate == tail:
ostate = conductor
elif istate == empty:
ostate = empty
else: # istate == conductor
n = sum( currentworld[y+dy][x+dx] == head
for dx,dy in ( (-1,-1), (-1,+0), (-1,+1),
(+0,-1), (+0,+1),
(+1,-1), (+1,+0), (+1,+1) ) )
ostate = head if 1 <= n <= 2 else conductor
return ostate
def nextgen(ww):
'compute next generation of wireworld'
world, width, height = ww
newworld = copy.deepcopy(world)
for x in range(1, width+1):
for y in range(1, height+1):
newworld[y][x] = newcell(world, x, y)
return WW(newworld, width, height)
def world2string(ww):
return '\n'.join( ''.join(row[1:-1]).rstrip() for row in ww.world[1:-1] )
ww = readfile(infile)
infile.close()
for gen in range(10):
print ( ("\n%3i " % gen) + '=' * (ww.w-4) + '\n' )
print ( world2string(ww) )
ww = nextgen(ww)