a couple of things I don't understand wrt lists

2013-04-16 Thread aaB
hello,

I am a beginner programmer. I started learning programming about a year and a
half ago, using C. I picked up python a few months ago, but only wrote very few
scripts.

I am currently trying to learn more about the python way of doing things by
writing a script that generates png images using a 1D cellular automaton.

While writing preliminary code for that project, I ran into a behaviour that I
don't understand.
I am using python 2.7 on a linux system.

I represent the CA's rule with a list of integers, of value 1 or 0.
Here is the function I use to generate the list:

def get_rule(rulenum):
  rule = []
  while rulenum > 0:
rule.append(rulenume % 2)
rulenum /= 2
  while len(rule) < 8:
rule.append(0)
  rule.reverse()
  return rule

if i call it by writing:

rule = getrule(int(8))

and then call:

print rule

the output is good:

[0, 0, 0, 0, 1, 0, 0, 0]


I then tried to print each item of the list using a for loop:

for i in range(rule):
  print rule[i]

the output is, as expected:
0
0
0
0
1
0
0
0

but when I do:

for i in rule:
  print rule[i]

I get the "complement":
1
1
1
1
0
1
1
1

There must be something I didn't understand correctly in the for statement, but
I really can't think of a reason why the output is what it is.
I tried this using the interactive console, and the results are the same,
whatever the length of the list, i always get the complement of my bit pattern.

Any pointers to help me understand this would be appreciated.
I am also running into an other issue with this script, but I'd rather
understand this before asking further questions.

Thanks, and sorry for the rather long post.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: a couple of things I don't understand wrt lists

2013-04-17 Thread aaB
Hello,

Thanks for all your replies, things are getting clearer.


- copy/paste vs retyping:
Several people have remarked that I had retyped instead of copy/pasting.
This is exactly what happened, the fact is I haven't figured out yet how to
enable copy/pasting from urxvt to vim.
I'll try to get this done before posting output from an interactive session.


- iterating a list:
If I understand what you've told me,

bitpattern = [1, 0, 0, 1, 1, 0, 1]
for bit in bitpattern: 
  print bit

and 

bitpattern = [1, 0, 0, 1, 1, 0, 1]
for i in range(len(bitpattern)): 
  print bitpattern[i]

are equivalent, the former being more "python" and the latter being something
like C written using python syntax.


- the "complement" thing:
I haven't yet tried to reproduce this, but I will, and I will post back if I see
this happening again, this time with a real log of python's interactive console,
or a complete script which people can use.


- list comprehension:
I wasn't at all aware of this, thanks a lot for pointing it out.
I had an other function that generated a list of cells for the CA, each cell
being randomly alive or dead.
I have rewritten it using list comprehension,

def populate(n):
  random.seed()
  return [random.randint(0,1) for i in range(n)]

which works the same as my previous, C-like, version but feels much better.

I might come back to you all but you've already given me a good push forward, so
I guess I'll be trying to use it as much as I can before asking for an other.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: a couple of things I don't understand wrt lists

2013-04-18 Thread aaB
Hello,

I am still in the process of writing preliminary code for my CA project.
I am now running into a behavior that I can't explain.

Here is a script which, at least on my system, shows the issue (python2.7 on a
linux system).
The final project will be wrapping these functions (and others) into a class
which will be in a module which can be imported into a script.

#!/usr/bin/python2

import sys
import random

def get_rule(rulenum):
  bitpattern = bin(rulenum)[2:]
  return [0]*(8-len(bitpattern)) + [int(bit) for bit in bitpattern]

def populate(n):
  random.seed()
  return [random.randint(0,1) for i in range(n)]

def get_index(thisgen, i):
  n = len(thisgen)-1
  cell = thisgen[i]
  if i is 0:
print "i==0"
prev, next = thisgen[n], thisgen[i+1]
  elif i is n:
print "i==%d" % n
prev, next = thisgen[i-1], thisgen[0]
  else:
prev, next = thisgen[i-1], thisgen[i+1]
  return prev*4 + cell*2 + next

def get_nextgen(thisgen, rule):
  return [rule[get_index(thisgen, i)] for i in range(len(thisgen))]


if len(sys.argv) == 2:
  n = int(sys.argv[1])
else:
  n = 257

rule = get_rule(145)
thisgen = populate(n)
nextgen = get_nextgen(thisgen, rule)
print "done for n == 257"

n = 258
thisgen = populate(n)
nextgen = get_nextgen(thisgen, rule)


My issue is that when n == 257, the script runs as expected, but if n >= 258, I
get an "IndexError: list index out of range".
The script is also attached to the email in case someone would like to try it on
their machine.
The print statements in the get_index() function's branching show me that, when 
I
get the "out of range" error, the program doesn't enter the "elif i is n"
condition, although it does for lower values of n.
I'm sorry, but I still haven't found a way to copy/paste from the terminal to
vim.
This behaviour occurred previously and had stopped when I used an other version
of the get_index() function. At that time, get_index() wasn't a function and was
just conditional branching inside get_nextgen, I wanted to use the list
comprehension syntax to build nextgen, and this got me into seperating the
get_index() routine. 
#!/usr/bin/python2

import sys
import random

def get_rule(rulenum):
  bitpattern = bin(rulenum)[2:]
  return [0]*(8-len(bitpattern)) + [int(bit) for bit in bitpattern]

def populate(n):
  random.seed()
  return [random.randint(0,1) for i in range(n)]

def get_index(thisgen, i):
  n = len(thisgen)-1
  cell = thisgen[i]
  if i is 0:
print "i==0"
prev, next = thisgen[n], thisgen[i+1]
  elif i is n:
print "i==%d" % n
prev, next = thisgen[i-1], thisgen[0]
  else:
prev, next = thisgen[i-1], thisgen[i+1]
  return prev*4 + cell*2 + next

def get_nextgen(thisgen, rule):
  return [rule[get_index(thisgen, i)] for i in range(len(thisgen))]


if len(sys.argv) == 2:
  n = int(sys.argv[1])
else:
  n = 257

rule = get_rule(145)
thisgen = populate(n)
nextgen = get_nextgen(thisgen, rule)
print "done for n == 257"

n = 258
thisgen = populate(n)
nextgen = get_nextgen(thisgen, rule)
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: a couple of things I don't understand wrt lists

2013-04-18 Thread aaB
> The second guess, more likely, is that you're using "is" to compare
> numbers, and that's never a safe idea.  It might happen to work for
> small numbers, but you should be using ==.
The second guess was right, changing "is" for "==" solved it, thanks.
I still have a lot to learn about python semantics.

The 8 bit pattern is used to store the rule, not the cells.
To compute the next cell, I index the rule list, based on the values of that 
cell
and it's two immediate neighbours in the previous generation.
This probably isn't the simplest way.
Since I am using only 3 cells to compute 1 cell, the biggest index would be
2**3 - 1, hence the 8bit pattern for the rule.
-- 
http://mail.python.org/mailman/listinfo/python-list