Re: [Tutor] Re: The Game of Life

2005-01-06 Thread Max Noel
On Jan 6, 2005, at 21:20, Brian van den Broek wrote:
Oh, the Life rules allow a world where every cell will change in 
the next generation, iff your world is a torus (i.e. the lower row 
touches the upper row as if it were immediately above it, and the 
right column touches the left column as if it were immediately left 
of it). It is quite trivial: set all cells to LIVE. Next generation 
they're all DEAD.
Topologist! (That's cheating!) ;-)
If we are going that way, you 'iff' seems a bit hasty. Take the 1x1 
matrix 'full' of live cells.
	Well, if the only cell of a 1x1 torus matrix is LIVE, that  means it 
is surrounded by 4 LIVE cells, doesn't it? :D

Also, other 'funny' (in the sense that a torus is funny) planes could 
be defined (say a torus-like structure with more than 1 whole -- 
cannot recall the general terminology from ill-remembered topology), 
etc. I meant the claim for a standard non-trivial (i.e. M  1 and N  
1) MxN euclidean plane matrix, but your correction is both amusing and 
welcome.
	Thanks :)
	However, the main reason why I talked about a torus is that it's one 
of the two obvious choices when you're implementing Life using a 2D 
matrix (the other being a finite rectangular plane).

-- Max
maxnoel_fr at yahoo dot fr -- ICQ #85274019
Look at you hacker... A pathetic creature of meat and bone, panting 
and sweating as you run through my corridors... How can you challenge a 
perfect, immortal machine?

___
Tutor maillist  -  Tutor@python.org
http://mail.python.org/mailman/listinfo/tutor


[Tutor] Re: The Game of Life

2005-01-06 Thread Brian van den Broek
Hi all,
after making the sketch I posted a bit ago, I tried to turn to actual
work. But, the bug had bit. ;-) So, here is an attempt at filling out
that sketch in an OOP way. (It is my second OOP program, so if anyone
was so inclined, I'd very much appreciate any comments. Also, I have a 
question about a snag I ran into while debugging.)

I'm also not too used to sharing complete code. I'd put it in the public
domain, but since so much of it was derived from Danny's code, I don't
really know the conventions for so doing. (Were I to know it
appropriate, I'd follow the copyright comment line with:
# This software is released into the public domain.
# Fold, spindle, or mutilate at will
I've attached it rather than pasted it, as with something 100 lines I
don't feel up to shortening line for email. Sorry 'bout that.
The question:
In an earlier version, instead of the run_world() method I now have, I
put the following within my class definition and after (i.e. outside of)
the method defs:
.while self.current_generation  self.total_generations:
.time.sleep(self.sleep_interval)
.self.update_world()
.self.print_world()
which caused this:
Traceback (most recent call last):
   File D:\Python Files\foogame_of_life.py, line 3, in -toplevel-
 class life_world:
   File D:\Python Files\foogame_of_life.py, line 76, in life_world
 while self.current_generation  self.total_generations:
NameError: name 'self' is not defined
That surprised me -- I'd have guessed that within a class, self was
everywhere defined, and not just within methods.
Clearly, I'm confused about something.
Anyway, thanks for reading. Best to all,
Brian vdB
# pylife.py
# Version 0.1
# Brian van den Broek
# [EMAIL PROTECTED]
# 2005-01-06 Thursday 17:41
# Copyright 2005

'''An OOP and ASCII based representation of Conway's Game of Life.
Much of the code was inspired by a post of Danny Yoo's on 2005-01-03 04:11
to the Python Tutor List. (You can find that post by searching the archives at
http://mail.python.org/pipermail/tutor/.)

I make no claims to ellegance or efficency -- this is only the second OOP I
have written.'''

import random, time

class life_world:

def __init__(self, X, Y, sleep_interval = 0.5, total_generations = 20):
self.X = X
self.Y = Y
self.world = self.seed_world()
self.sleep_interval = sleep_interval
self.total_generations = total_generations
self.current_generation = 0
self.print_world()

def seed_world(self):
'''Constructs a new random world of size XxY.'''

world = {}
for j in range(self.X):
for i in range(self.Y):
world[i, j] = random.choice((True, False))
return world

def print_world(self):
'''Prints out a string representation of a world.'''

print '\n\nGeneration Number: %s\n' %self.current_generation
print '--'*(self.Y + 1) + '-'
for j in range(self.X):
print '|',
for i in range(self.Y):
if self.world[i, j]:
print 'X',
else:
print ' ',
print '|'
print '--'*(self.Y + 1) + '-'

def count_neighbours(self, cell):
'''Returns the number of live neighbours to this one.

'neghboUrs because I'm Canadian, eh.
'''
live_count = 0
i,j = cell
for i_delta in [-1, 0, 1]:
for j_delta in [-1, 0, 1]:
if (i_delta, j_delta) == (0, 0):
continue
try:
# To deal with the edges of the matrix, where the
# deltas can take us out of bounds.
if self.world[i+i_delta, j+j_delta]:
live_count += 1
except KeyError:
pass
return live_count

def cell_will_change(self, cell):
'''Returns True if a cell will change, False otherwise.'''
change = False
if self.world[cell] and not self.count_neighbours(cell) in (2,3):
change = True
if not self.world[cell] and self.count_neighbours(cell) == 3:
change = True
return change

def get_changed_cells_list(self):
'''Returns a list of cells that will change in the next generation.'''

changed_cells_list = []
for c in self.world:
if self.cell_will_change(c):
changed_cells_list.append(c)
return changed_cells_list

def update_world(self):
'''Produces the next generation world.'''
self.current_generation += 1
changed_cells_list = self.get_changed_cells_list()
for c in changed_cells_list:
self.world[c] = not self.world[c]

def run_world(self):
while self.current_generation  self.total_generations:
time.sleep(self.sleep_interval)
self.update_world()
  

Re: [Tutor] Re: The Game of Life

2005-01-06 Thread Kent Johnson
Brian van den Broek wrote:
In an earlier version, instead of the run_world() method I now have, I
put the following within my class definition and after (i.e. outside of)
the method defs:
.while self.current_generation  self.total_generations:
.time.sleep(self.sleep_interval)
.self.update_world()
.self.print_world()
which caused this:
Traceback (most recent call last):
   File D:\Python Files\foogame_of_life.py, line 3, in -toplevel-
 class life_world:
   File D:\Python Files\foogame_of_life.py, line 76, in life_world
 while self.current_generation  self.total_generations:
NameError: name 'self' is not defined
That surprised me -- I'd have guessed that within a class, self was
everywhere defined, and not just within methods.
self is just another method parameter. OK not quite, but it is a method parameter and it is only 
bound within the scope of the method. There is nothing magic about the name, either; it is just a 
(strong) convention.

In fact, by using a different name for self and the magic of lexical scoping and closures, you can 
do something very much like Java inner classes - make a nested class that has access to all the 
attributes of the enclosing class.

This is off-topic and a bit twisted, but I'm not going to let that stop me:
''' Make a nested class that has access to the attributes of its parent class 
'''
class Outer:
def __init__(outerSelf, x):
outerSelf.x = x
def makeNested(outerSelf, x):
class Nested:
def __init__(innerSelf, x):
innerSelf.x = x
def showX(innerSelf):
print 'outer x is', outerSelf.x
print 'inner x is', innerSelf.x
return Nested(x)
o = Outer(3)
n = o.makeNested(5)
n.showX()
o.x = 22
n.showX()

prints:
outer x is 3
inner x is 5
outer x is 22
inner x is 5
Kent
Clearly, I'm confused about something.
Anyway, thanks for reading. Best to all,
Brian vdB

# pylife.py
# Version 0.1
# Brian van den Broek
# [EMAIL PROTECTED]
# 2005-01-06 Thursday 17:41
# Copyright 2005
'''An OOP and ASCII based representation of Conway's Game of Life.
Much of the code was inspired by a post of Danny Yoo's on 2005-01-03 04:11
to the Python Tutor List. (You can find that post by searching the archives at
http://mail.python.org/pipermail/tutor/.)
I make no claims to ellegance or efficency -- this is only the second OOP I
have written.'''
import random, time
class life_world:

def __init__(self, X, Y, sleep_interval = 0.5, total_generations = 20):
self.X = X
self.Y = Y
self.world = self.seed_world()
self.sleep_interval = sleep_interval
self.total_generations = total_generations
self.current_generation = 0
self.print_world()

def seed_world(self):
'''Constructs a new random world of size XxY.'''

world = {}
for j in range(self.X):
for i in range(self.Y):
world[i, j] = random.choice((True, False))
return world
def print_world(self):
'''Prints out a string representation of a world.'''
print '\n\nGeneration Number: %s\n' %self.current_generation
print '--'*(self.Y + 1) + '-'
for j in range(self.X):
print '|',
for i in range(self.Y):
if self.world[i, j]:
print 'X',
else:
print ' ',
print '|'
print '--'*(self.Y + 1) + '-'

def count_neighbours(self, cell):
'''Returns the number of live neighbours to this one.

'neghboUrs because I'm Canadian, eh.
'''
live_count = 0
i,j = cell
for i_delta in [-1, 0, 1]:
for j_delta in [-1, 0, 1]:
if (i_delta, j_delta) == (0, 0):
continue
try:
# To deal with the edges of the matrix, where the
# deltas can take us out of bounds.
if self.world[i+i_delta, j+j_delta]:
live_count += 1
except KeyError:
pass
return live_count
def cell_will_change(self, cell):
'''Returns True if a cell will change, False otherwise.'''
change = False
if self.world[cell] and not self.count_neighbours(cell) in (2,3):
change = True
if not self.world[cell] and self.count_neighbours(cell) == 3:
change = True
return change
def get_changed_cells_list(self):
'''Returns a list of cells that will change in the next generation.'''
changed_cells_list = []
for c in self.world:
if self.cell_will_change(c):
changed_cells_list.append(c)
return changed_cells_list
def update_world(self):
'''Produces the next