Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Python > nested lists as arrays

Reply
Thread Tools

nested lists as arrays

 
 
benjamin.cordes@blawrc.de
Guest
Posts: n/a
 
      02-14-2005
Hi,

why can't I do this:

dummy = self.elements[toy][tox]

self.elements[toy][tox] = self.elements[fromy][fromx]
self.elements[fromy][fromx] = dummy

after initialising my nested list like this:

self.elements = [[0 for column in range(dim)] for row in
range(dim) ]

 
Reply With Quote
 
 
 
 
Diez B. Roggisch
Guest
Posts: n/a
 
      02-14-2005
http://www.velocityreviews.com/forums/(E-Mail Removed) wrote:

> Hi,
>
> why can't I do this:
>
> dummy = self.elements[toy][tox]
>
> self.elements[toy][tox] = self.elements[fromy][fromx]
> self.elements[fromy][fromx] = dummy
>
> after initialising my nested list like this:
>
> self.elements = [[0 for column in range(dim)] for row in
> range(dim) ]


Works for me:

dim = 10
elements = [[0 for column in xrange(dim)] for row in
xrange(dim) ]

toy, tox = (2,5)
fromy, fromx = (7,5)

dummy =elements[toy][tox]
elements[toy][tox] = elements[fromy][fromx]
elements[fromy][fromx] = dummy


And use xrange instead of range.
--
Regards,

Diez B. Roggisch
 
Reply With Quote
 
 
 
 
bruno modulix
Guest
Posts: n/a
 
      02-14-2005
(E-Mail Removed) wrote:
> Hi,
>
> why can't I do this:
>
> dummy = self.elements[toy][tox]
>
> self.elements[toy][tox] = self.elements[fromy][fromx]
> self.elements[fromy][fromx] = dummy
>
> after initialising my nested list like this:
>
> self.elements = [[0 for column in range(dim)] for row in
> range(dim) ]
>


Sorry, I'm not psychic enough to guess what is exactly your problem:
- what do you mean "can't do" ? You have a traceback ? please post it.
You have unexpected results ? please describe.
- what are self, dim, toy, tox, fromy, fromx ?
- is all that code in the same method ?
- etc etc

So please post more informations if you expect us to help you.


Note that the following code is correct:
>>> l = [[0 for i in range(3)] for y in range(3)]
>>> l

[[0, 0, 0], [0, 0, 0], [0, 0, 0]]
>>> l[0][0] = 1
>>> l

[[1, 0, 0], [0, 0, 0], [0, 0, 0]]
>>> l[0][0], l[0][1] = l[0][1], l[0][0]
>>> l

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


So I guess that your problem has nothing to do with nested lists.

(Also note BTW that, thanks to the magic of multiple assignement, you
don't need the dummy stuff. The pythonic idiom for swapping 2 bindings is
a, b = b, a)



--
bruno desthuilliers
python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
p in '(E-Mail Removed)'.split('@')])"
 
Reply With Quote
 
benjamin.cordes@blawrc.de
Guest
Posts: n/a
 
      02-14-2005

Diez B. Roggisch wrote:
> (E-Mail Removed) wrote:
>
> > Hi,
> >
> > why can't I do this:
> >
> > dummy = self.elements[toy][tox]
> >
> > self.elements[toy][tox] = self.elements[fromy][fromx]
> > self.elements[fromy][fromx] = dummy
> >
> > after initialising my nested list like this:
> >
> > self.elements = [[0 for column in range(dim)] for row in
> > range(dim) ]

>
> Works for me:
>
> dim = 10
> elements = [[0 for column in xrange(dim)] for row in
> xrange(dim) ]
>
> toy, tox = (2,5)
> fromy, fromx = (7,5)
>
> dummy =elements[toy][tox]
> elements[toy][tox] = elements[fromy][fromx]
> elements[fromy][fromx] = dummy
>
>
> And use xrange instead of range.
> --
> Regards,
>
> Diez B. Roggisch


thanks so far, and sorry for posting the topic now 3 times.

 
Reply With Quote
 
benjamin.cordes@blawrc.de
Guest
Posts: n/a
 
      02-14-2005
Thanks for the code.
What I want to do is this:
I want to solve the block puzzle problem. The problem is as follows:
You have a nxn Array of Numbers and one empty space. Now you there are
up to four possible moves: up, right, down and left, so that each
neighbour of the empty slot can be moved there.

The method getEmptySlot is for getting the empty slot. The method
getPossibleMoves returns the possible moves. Perfoming a move is
swaping one element with the empty slot marked as -1.

The full executable code is appended.
The expected behaviour is that when the move is performed the
appropiate elements should be swaped. But for some reason every now and
then it swaps the wrong elements.

# Puzzle.py
# class for a sliding block puzzle

# an starting state of a 8-puzzle could look like the following:
# ------------
# | 7 2 4 |
# | |
# | 5 X 6 |
# | |
# | 8 3 1 |
# ------------

# the goal is to reach this state:
# ------------
# | X 1 2 |
# | |
# | 3 4 5 |
# | |
# | 6 7 8 |
# ------------

import random
import copy

class Puzzle:

def __init__(self, dim):
self.dim = dim
# self.elements = {}
# for column in range(dim):
# for row in range(dim):
# elements[(column, row)] = 0
self.elements = [[0 for column in range(dim)] for row in
range(dim) ]

def __str__(self):
s = ""
i = 0
j = 0
while i <= self.dim-1:
while j <= self.dim-1:
s = s + str(self.elements[j][i])
j=j+1
s = s + "\t"
i=i+1
j = 0
s = s + "\n"
return s

def compare(self, compareTo):
if (self.dim != compareTo.dim):
return 0
i = 0
j = 0
equal = 1
while i <= self.dim-1:
while j <= self.dim-1:
if self.elements[j][i] != compareTo.elements[j][i]:
equal = 0
j = j+1
i = i+1
return equal


def setAsGoalState(self):
# create elements of puzzle
i = 0
j = 0
while i <= self.dim-1:
while j <= self.dim-1:
self.elements[j][i] = i*3+j
j=j+1
j=0
i=i+1

# create empty element seperately
self.elements[0][0] = -1


def setRandomState(self):
# container for the elements to pick from
container = [1,2,3,4,5,6,7,8,-1]

# create elements of puzzle randomly
i = 0
j = 0
while i <= self.dim-1:
while j <= self.dim-1:
if len(container) > 0:
randomindex = random.randint(0,len(container)-1)
self.elements[j][i] = container[randomindex]
del container[randomindex]
j=j+1
else:
break
j=0
i=i+1

def getEmptySlot(self):
i = 0
j = 0
while i <= self.dim-1:
while j <= self.dim-1:
if self.elements[j][i] == -1:
return [j, i]
j = j+1
j = 0
i = i + 1

def performMove(self, direction):
slot = self.getEmptySlot()

if (direction == "up"):
self.swapElements(slot[1], slot[0], slot[1]+1, slot[0])

elif (direction == "down"):
self.swapElements(slot[1], slot[0], slot[1]-1, slot[0])

elif direction == "left":
self.swapElements(slot[1], slot[0], slot[1], slot[0]-1)
elif (direction == "right"):
self.swapElements(slot[1], slot[0], slot[1], slot[0]+1)

def swapElements(self, fromx, fromy, tox, toy):
dummy = self.elements[toy][tox]

self.elements[toy][tox] = self.elements[fromy][fromx]
self.elements[fromy][fromx] = dummy


def getChildren(self):
moves = self.getPossibleMoves()
self.children = []
for eachMove in moves:
newchild = copy.copy(self.performMove(eachMove))
try:
self.children.append(newchild)
except:
print "Exception: " + str(len(self.children))

def getPossibleMoves(self):
emptySlot = self.getEmptySlot()
y = emptySlot[1]
x = emptySlot[0]
north = (y == 0)
south = (y == (self.dim-1))
west = (x == 0)
east = (x == (self.dim-1))

middle = not(north or south or west or east)

northwest = north and west
northeast = north and east
southwest = south and west
southeast = south and east
# orientation has to be distinct
# save original values
orignorth = north
origsouth = south
# original north or south
orignors = north or south

north = north and not (west or east)
south = south and not (west or east)
west = west and not (orignors)
east = east and not (orignors)

if middle:
return ["up", "down", "left", "right"]
elif north:
return ["up", "left", "right"]
elif south:
return ["down", "left", "right"]
elif west:
return ["up", "down", "left"]
elif east:
return ["up", "down", "right"]
elif northwest:
return ["up", "left"]
elif northeast:
return ["up", "right"]
elif southwest:
return ["down", "left"]
elif southeast:
return ["down", "right"]

# ~Puzzle.py

# SolvePuzzleAgent.py
# imports
from Puzzle import *
from Tree import *
import bintree

# set up puzzle
puzzle = Puzzle(3)
puzzle.setRandomState()
goalpuzzlestate = Puzzle(3)
goalpuzzlestate.setAsGoalState()
print "goal state of the puzzle: "
print str(goalpuzzlestate)
print "start state of the puzzle: "
print str(puzzle)
#start search
tree = bintree.BinaryTree()

done = 0
currentBranch = 0
while not done:
tree.insert(puzzle)
# get the fringe
moves = puzzle.getPossibleMoves()
children = puzzle.getChildren()
#print "possible moves: " + str(moves)
print "moving: " + str(moves[currentBranch])
puzzle.performMove(moves[currentBranch])

# test if we're have reached the goal state
done = puzzle.compare(goalpuzzlestate)
print "done ? : " + str(done)
print "state:\n" + str(puzzle)
done = 1


print "search tree: " + str(tree.inorder())

# bintree.py
# a binary tree
class Node:
def __init__(self, val, left=None, right=None):
self.val = val
self.left = left
self.right = right

class BinaryTree:
def __init__(self):
self.root = None

def insert(self, val):
root = self.root
lastdir = None
while root:
lastroot = root
if val <= root.val:
lastdir = 'left'
root = root.left
else:
lastdir = 'right'
root = root.right
new = Node(val)
if lastdir is None:
self.root = new
elif lastdir == 'left':
lastroot.left = new
else:
lastroot.right = new

def insertList(self, list):
for x in list:
self.insert(x)


def inorder(self):
result = []
self.__helper(self.root, result)
return result

def __helper(self, root, result):
if root is not None:
self.__helper(root.left, result)
result.append(root.val)
self.__helper(root.right, result)

# ~bintree.py

 
Reply With Quote
 
Terry Reedy
Guest
Posts: n/a
 
      02-14-2005

"Diez B. Roggisch" <(E-Mail Removed)> wrote in message >

>And use xrange instead of range.


For small dimensions like 3,4,5, xrange is way overkill and perhaps takes
both more space and time. Since dim is a constant for a given puzzle, I
would set self._range = range(dim) in __init__() and use that to iterate.
And, as I said in another response, I would not iterate to make a move.

Terry J. Reedy




 
Reply With Quote
 
Terry Reedy
Guest
Posts: n/a
 
      02-14-2005

<(E-Mail Removed)> wrote in message
news:(E-Mail Removed) ups.com...
> def setRandomState(self):
> # container for the elements to pick from
> container = [1,2,3,4,5,6,7,8,-1]
>
> # create elements of puzzle randomly
> i = 0
> j = 0
> while i <= self.dim-1:
> while j <= self.dim-1:
> if len(container) > 0:
> randomindex = random.randint(0,len(container)-1)
> self.elements[j][i] = container[randomindex]
> del container[randomindex]
> j=j+1
> else:
> break
> j=0
> i=i+1


Without reading closely, I believe that the above can generate any possible
position. Are you aware that half are unsolvable? If that matters, you
need to either find a book or site that explains the parity test for
solvability or generate the start position from the goal position by a
series of random moves.

Terry J. Reedy




 
Reply With Quote
 
Michael Spencer
Guest
Posts: n/a
 
      02-14-2005
Terry Reedy wrote:
> <(E-Mail Removed)> wrote in message
> news:(E-Mail Removed) ups.com...
>
>> def setRandomState(self):
>> # container for the elements to pick from
>> container = [1,2,3,4,5,6,7,8,-1]
>>
>> # create elements of puzzle randomly
>> i = 0
>> j = 0
>> while i <= self.dim-1:
>> while j <= self.dim-1:
>> if len(container) > 0:
>> randomindex = random.randint(0,len(container)-1)
>> self.elements[j][i] = container[randomindex]
>> del container[randomindex]
>> j=j+1
>> else:
>> break
>> j=0
>> i=i+1

>
>
> Without reading closely, I believe that the above can generate any possible
> position. Are you aware that half are unsolvable? If that matters, you
> need to either find a book or site that explains the parity test for
> solvability or generate the start position from the goal position by a
> series of random moves.
>
> Terry J. Reedy
>

This covers the test for solvability - enjoy :
http://www.cs.tcd.ie/publications/te...CS-2001-24.pdf

BTW, just because your puzzle looks like a grid doesn't neceesarily mean that
representing the data as nested arrays is easiest. A flat list might be just as
good here. It simplifies some of the operations (creating a random ordering
becomes a one-liner), at the expense of a little more complexity in some others:

import random
class n2grid(object):
"""A grid for the n squared puzzle"""
def __init__(self,dim = 4):
self.cells = range(dim*dim)
self.dim = dim
self.pos = (0,0)
def shuffle(self):
random.shuffle(self.cells)
self.pos = divmod(self.cells.index(0),self.dim)
def show(self):
for row in self._asarray():
print "".join("[%2s]" % (cell or "") for cell in row)
def _move(self,dy,dx):
dim = self.dim
cells = self.cells
oldy, oldx = self.pos
newy, newx = oldy + dy, oldx + dx
if 0 <= newx < dim and 0 <= newy < dim:
ix = newy * dim + newx
ox = oldy * dim + oldx
cells[ix], cells[ox] = cells[ox], cells[ix]
self.pos = newy,newx
else:
raise Exception, "Illegal move to: (%s,%s)" % (newy, newx)
def move(self, dx, dy):
try:
self._move(dx,dy)
self.show()
except:
pass

def _asarray(self): #create the array representation when needed
cells = iter(self.cells)
dim = self.dim
return [[cells.next() for j in range(dim)] for i in range(dim)]

def __repr__(self):
return repr(self._asarray())




>>> p = n2grid()
>>> p.show()

...
[ ][ 1][ 2][ 3]
[ 4][ 5][ 6][ 7]
[ 8][ 9][10][11]
[12][13][14][15]
>>> p.shuffle()
>>> p.show()

[ 3][15][ 6][ 7]
[10][ ][12][ 5]
[ 4][ 1][14][ 8]
[ 2][11][13][ 9]
>>> p.move(1,1)

[ 3][15][ 6][ 7]
[10][14][12][ 5]
[ 4][ 1][ ][ 8]
[ 2][11][13][ 9]
>>> p.move(1,0)

[ 3][15][ 6][ 7]
[10][14][12][ 5]
[ 4][ 1][13][ 8]
[ 2][11][ ][ 9]
>>> p.move(1,0) # illegal (does nothing)
>>>


Cheers
Michael

 
Reply With Quote
 
bruno modulix
Guest
Posts: n/a
 
      02-15-2005
(E-Mail Removed) a écrit :
> Thanks for the code.
> What I want to do is this:
> I want to solve the block puzzle problem. The problem is as follows:
> You have a nxn Array of Numbers and one empty space. Now you there are
> up to four possible moves: up, right, down and left, so that each
> neighbour of the empty slot can be moved there.
>
> The method getEmptySlot is for getting the empty slot. The method
> getPossibleMoves returns the possible moves. Perfoming a move is
> swaping one element with the empty slot marked as -1.
>
> The full executable code is appended.

s/executable/source/ !-)

> The expected behaviour is that when the move is performed the
> appropiate elements should be swaped. But for some reason every now and
> then it swaps the wrong elements.


So the problem is not that you "can't" swap 2 elements, but that there
seems to be some logical bug(s) in your code.

> # Puzzle.py
> # class for a sliding block puzzle
>

(snip)

> import random
> import copy
>
> class Puzzle:
>
> def __init__(self, dim):
> self.dim = dim
> self.elements = [[0 for column in range(dim)] for row in
> range(dim) ]


So at this stage you've got 3 rows of 3 colums:
[
['row 0 - col 0', 'row 0 - col 1', 'row 0 - col 2'],
['row 1 - col 0', 'row 1 - col 1', 'row 1 - col 2'],
['row 2 - col 0', 'row 2 - col 1', 'row 2 - col 2']
]

Is that right ?

> def __str__(self):
> s = ""
> i = 0
> j = 0
> while i <= self.dim-1:

ok, looping on rows

> while j <= self.dim-1:

and now looping on columns in current row...

> s = s + str(self.elements[j][i])


oops ! Looks like you're addressing row[j] column[i] instead of row[i]
column[j] !-)

> j=j+1
> s = s + "\t"
> i=i+1
> j = 0
> s = s + "\n"
> return s


(snip the rest of the code)

Ok, let's try with a slightly more pythonic (and thus more readable)
version of this code (I used another method name so we can compare both
versions):

def to_string(self):
s = []
for row in self.elements:
for col in row:
s.append('%d\t' % col)
s.append('\n')
return ''.join(s)

For testing purpose, let's modify the __init__ a bit (this will break
the code but what, it's just to check something, we can get back to
original code later):

def __init__(self, dim):
self.dim = dim
self.range = range(self.dim)
#self.elements = [[0 for column in self.range] for row in self.range]
self.elements = [[int('%d%d' % (row, column)) for column in
self.range] for row in self.range]
# check we have a correct layout, remove me when fixed:
print "%s" % self.elements

and now let's try:
>>> p = Puzzle(3)

[[0, 1, 2], [10, 11, 12], [20, 21, 22]]

so far, so good, we have 3 rows of 3 columns each.
let's continue:
>>> print p.to_string()

0 1 2
10 11 12
20 21 22

Ok, so our new to_string() method is ok. Now the real test:
>>> print p

0 10 20
1 11 21
2 12 22

Remember ?
"""
oops ! Looks like you're addressing row[j] column[i] instead of row[i]
column[j]
"""

Looks like we found one bug...

Let's continue and rewrite some more code:

def compare(self, other):
if (self.dim != other.dim):
return False

for self_row, other_row in zip(self.elements, other.elements):
for self_col, other_col in zip(self_row, other_row):
if self_col != other_col:
return False

return True

Ok, that one was easy. Let's try with another one

def getEmptySlot(self):
for row in self.elements:
for cell in row:
if cell == -1:
return ???

Mmmm... won't work. Seems we need indices here, let's try again:

def getEmptySlot(self):
for row in self.range:
for col in self.range:
if self.elements[row][col] == -1:
return (row, col)

Ok, not so clean but still readable (notice how using explicit names
like 'row' and 'col' helps understanding the code...).

Now let's do the swap:

def swapElements(self, from_cell, to_cell):
from_row, from_col = from_cell
to_row, to_col = to_cell
elts = self.elements
elts[to_row][to_col], elts[from_row][from_col] =
elements[from_row][from_col], elts[to_row][to_col]

Mmmm... this begins to smell. I don't like having to split the coords
like this. I'd prefer something like:

def swapElements(self, from_cell, to_cell):
self.elements[from_cell], self.elements[to_cell] \
= self.elements[to_cell], self.elements[from_cell]

This could be possible if we used another data structure. Something like
a dict of coords:value pairs. We could build it like this:

def __init__(self, dim):
self.dim = dim
self.range = range(self.dim)
self.elements = {}
for row in self.range:
for col in self.range:
self.elements[(row,col)] = 0

and then the search for the empty slot:

def getEmptySlot(self):
for coords, value in self.elements.items():
if value == -1:
return coords
assert(False) # shouldn't be here anyway !

Hey, that looks nicer, isn't it ? But what with the __str__() method ?
We can't use the dict.items() method since dicts are not ordered. But we
can recompute the keys... What about :

def __str__(self):
s = []
for row in self.range:
for col in self.range:
s.append("%d\t" % self.elements[(row, col)])
s.append('\n')
return ''.join(s)

Was not so difficult, finally. Now the compare() has to be rewritten too:

def compare(self, other):
if (self.dim != other.dim):
return 0

for row in self.range:
for col in self.range:
if self.elements[(row,col)] != other.elements[(row,col)]:
return False
# no difference
return True

Err... Wait a minute... What are we doing here ? Comparing 2 dicts ?
Wait, wait, let's check something...

>>> '__eq__' in dir(dict)

True

Haha ! Our good'ole dict already has an 'equality' special method... Now
is this a 'value' or 'identity' equality ?

>>> d1 = {1:1, 2:2}
>>> d2 = {2:2, 1:1}
>>> d1 == d2

True

Bingo ! Play it again, sam :

def compare(self, other):
return self.elements == other.elements

Hehehe. Less code, better code, as grand'ma used to say !-)

Now the fine part : let's make it move. What was it like ?

def performMove(self, direction):
slot = self.getEmptySlot()
if (direction == "up"):
self.swapElements(slot[1], slot[0], slot[1]+1, slot[0])
elif (direction == "down"):
self.swapElements(slot[1], slot[0], slot[1]-1, slot[0])
elif direction == "left":
self.swapElements(slot[1], slot[0], slot[1], slot[0]-1)
elif (direction == "right"):
self.swapElements(slot[1], slot[0], slot[1], slot[0]+1)

This won't work since our swapElements() method now expects 2 tuples.
Let's look closer. The first pair is always the same, it's the actually
the empty slot. Quite sensible. We just have to create the second tuple
from the first. And BTW, I don't like the if/elif neither. What about
using a dict again ? :

def performMove(self, direction):
slot = self.getEmptySlot()
to_slot = {'up' : lambda (row, col): (row-1, col),
'down' : lambda (row, col): (row+1, col),
'left' : lambda (row, col): (row, col-1),
'right': lambda (row, col): (row, col+1)}
self.swapElements(slot, to_slot[direction](slot))

Better, but not quite ok: it's silly to recreate the to_slot dict each
time. Let's put it in the __init__ :

def __init__(self, dim):
self.dim = dim
self.range = range(self.dim)
self.elements = {}

for row in self.range:
for col in self.range:
self.elements[(row,col)] = 0

self.to_slot = {'up' : lambda (row, col): (row-1, col),
'down' : lambda (row, col): (row+1, col),
'left' : lambda (row, col): (row, col-1),
'right': lambda (row, col): (row, col+1)}


and now our performMove() method become:

def performMove(self, direction):
slot = self.getEmptySlot()
self.swapElements(slot, self.to_slot[direction](slot))


Begins to look better, isn't it ? Ok, your turn to play !-)
Just two more things :

1/
getPossibleMoves(self):
emptySlot = self.getEmptySlot()
y = emptySlot[1]
x = emptySlot[0]
(...)

could benefit from being rewritten as:

getPossibleMoves(self):
row, col = self.getEmptySlot()
(...)

(Yes, Python will automagically 'unpack' the tuple !-)

2/
def getChildren(self):
moves = self.getPossibleMoves()
self.children = []
for eachMove in moves:
newchild = copy.copy(self.performMove(eachMove))

performMove() doesn't explicitly return anything, so it implicitly
returns None. This may not give you what you want !-)

If the idea is to 'capture' the state of the puzzle object, you may want
to have performMove() returning self. *But* remember that the state of
the puzzle object is affected by performMove(), so this may not behave
as expected either, since after each move, the possible moves change.

So the solution would be to 'clone' self *before* each performMove(),
call the performMove() on each clone and store the clone.

(BTW, the name of the method may be somewhat misleading, and I'm not
sure this method really belongs to the Puzzle class. )

and finally (pun intend !-) :

try:
self.children.append(newchild)
except:
print "Exception: " + str(len(self.children))

This is the only place where you handle exceptions. But there is no
particular reason to expect an exception here. So your try/except block
is useless. Worse, it's badly coded, since you don't specify which
exception you want to catch. This may put you into troubles (probably
not here, but... I recently had hard time to debug some code that had
many 'catch-all' except clauses.)

Well... You seem to like puzzles, so I leave it up to you to finish that
one.

*warning* : this 100% untested code. You should write some unit tests to
make sure every method woks as expected.

HTH
Bruno
 
Reply With Quote
 
benjamin.cordes@blawrc.de
Guest
Posts: n/a
 
      02-20-2005
great thanks

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Multidimensional arrays and arrays of arrays Philipp Java 21 01-20-2009 08:33 AM
List of lists of lists of lists... =?UTF-8?B?w4FuZ2VsIEd1dGnDqXJyZXogUm9kcsOtZ3Vleg==?= Python 5 05-15-2006 11:47 AM
nested lists as arrays naturalborncyborg Python 5 02-14-2005 06:44 PM
Problem with nested lists as arrays benjamin.cordes@blawrc.de Python 2 02-14-2005 05:31 PM
Sorting lists of lists... JustSomeGuy C++ 0 06-17-2004 05:44 PM



Advertisments