I'm using python 2.5 (I know it's an old version) and I keep getting a very frustrating 'List index out of range' exception. I'm working on a tile based game, and bellow is the code for creating the map I'm having issues with:
#Creates the list
def setMapSize(self):
l = raw_input('Custom Map length: ')
h = raw_input('Custom Map height: ')
if not(l=='')and not(h==''):
self.length = int(l)
self.height = int(h)
self.tileMap = [[i]*self.length for i in xrange(self.height)]
print self.tileMap
#Load each element of the list from a text file
def loadMap(self,filePath='template.txt'):
loadPath = raw_input('Load the map: ')
if loadPath =='':
self.directory = 'c:/Python25/PYGAME/TileRpg/Maps/' + filePath
print 'Loading map from ',self.directory
readFile = open(self.directory,'r')
for y in xrange(self.height):
for x in xrange(self.length):
#reads only 1 byte (1 char)
print '---Location: ',x,y
print self.tileMap
self.tileMap[x][y]=int(readFile.read(1))
print 'Loaded map:',self.tileMap
readFile.close()
print 'Map loaded\n'
Here is the output and error message I get, please tell me if you know what's going on:
Main began
Map began initialization
Map initialized
Custom Map length: 2
Custom Map height: 5
[[0, 0], [0, 0], [0, 0], [0, 0], [0, 0]]
Load the map:
Loading map from c:/Python25/PYGAME/TileRpg/Maps/template.txt
---Location: 0 0
[[0, 0], [0, 0], [0, 0], [0, 0], [0, 0]]
---Location: 1 0
[[9, 0], [0, 0], [0, 0], [0, 0], [0, 0]]
---Location: 0 1
[[9, 0], [9, 0], [0, 0], [0, 0], [0, 0]]
---Location: 1 1
[[9, 9], [9, 0], [0, 0], [0, 0], [0, 0]]
---Location: 0 2
[[9, 9], [9, 9], [0, 0], [0, 0], [0, 0]]
Traceback (most recent call last):
File "C:\Python25\PYGAME\TileRpg\LevelEditorMain.py", line 7, in <module>
class Main():
File "C:\Python25\PYGAME\TileRpg\LevelEditorMain.py", line 17, in Main
tileMap.loadMap()
File "C:\Python25\PYGAME\TileRpg\Map.py", line 48, in loadMap
self.tileMap[x][y]=int(readFile.read(1))
IndexError: list assignment index out of range
As you can see, the index I'm assigning to seems to exist, but I still get this error.
You swapped height and width; the outer list is of length height, not the inner. self.tileMap[0] is a list of length 2, so the maximum index you can use on it is 1, not 2.
Swapping x and y would solve this:
for x in xrange(self.height):
for y in xrange(self.length):
#reads only 1 byte (1 char)
print '---Location: ',x,y
print self.tileMap
self.tileMap[x][y]=int(readFile.read(1))
Not that you need to use indices here, you can alter the lists directly:
for row in self.tileMap:
row[:] = [readFile.read(1) for _ in row]
You can read a row at a time:
for row in self.tileMap:
row[:] = map(int, readFile.read(self.length))
Related
here is the problem I am trying to solve:
coord = [[0, 0], [1, 0], [1, 1], [2, 0], [2, 1], [2, 1], [2, 2] ..]
new_arr = [[[0, 0], 1], [[1, 0], 1], [[1, 1], 1], [[2, 0], 1], [[2, 1], 2], [[2, 2], 1] ..]
This is the target I am trying to map to
[0, 0][0, 1][0, 2]
[1, 0][1, 1][1, 2]
[2, 0][2, 1][2, 2]
the ultimate output would be the counts against each of the coordinates
1 0 0
1 1 0
1 2 1
------ clarifications --------
the goal is to generate this square of numbers (counts) which is the second element in new_arr. E.g. [[0, 0], 1], [[1, 0], 1], can be interpreted as the value 1 for the coordinate [0,0] and value 1 for coordinate [1,0]
the first list (coord) is simply a map of the coordinates. The goal is to get the corresponding value (from new_arr) and display it in the form of a square. Hope this clarified. The output will be a grid of the format
1 0 0
1 1 0
1 2 1
to the question of N (I just took a sample value of 3). The actual use case is when the user enters an integer, say 6 and the result is in a 6 X 6 square. The counts are chess move computations on the ways to reach a specific cell (two movements only (i+1, j) & (i+1, j+1) ....... starting from (0,0)
The logic is not fully clear, but is looks like you want to map the values of new_arr on the Cartesian product of coordinates:
N = 3 # how this is determined is unclear
d = {tuple(l):x for l, x in new_arr}
# {(0, 0): 1, (1, 0): 1, (1, 1): 1, (2, 0): 1, (2, 1): 2, (2, 2): 1}
out = [d.get((i,j), 0) for i in range(N) for j in range(N)]
# [1, 0, 0, 1, 1, 0, 1, 2, 1]
# 2D variant
out2 = [[d.get((i,j), 0) for j in range(N)] for i in range(N)]
# [[1, 0, 0],
# [1, 1, 0],
# [1, 2, 1]]
alternative with numpy
import numpy as np
N = 3
a = np.zeros((N,N), dtype=int)
# get indices and values
idx, val = zip(*new_arr)
# assign values (option 1)
a[tuple(zip(*idx))] = val
# assign values (option 2)
a[tuple(np.array(idx).T.tolist())] = val
print(a)
output:
array([[1, 0, 0],
[1, 1, 0],
[1, 2, 1]])
Use numpy:
import numpy as np
i = []
coord = [[0, 0], [1, 0], [1, 1], [2, 0], [2, 1], [2, 1], [2, 2]]
new_arr = [[[0, 0], 1], [[1, 0], 1], [[1, 1], 1], [[2, 0], 1], [[2, 1], 2], [[2, 2], 1]]
result = np.zeros([coord[-1][0] + 1, coord[-1][1] + 1])
for i in new_arr:
for j in coord:
if i[0] == j:
result[j[0],j[1]]= i[1]
print(result)
Output:
[[1. 0. 0.]
[1. 1. 0.]
[1. 2. 1.]]
I have 10 customers and one depot 0. For each customer I now want to create a shuttle route from depot, to customer and back to depot in the following format:
Shuttle_route_i = [0, i, 0]
But I don't want to create a dictionary, because later the routes will be changed, compiled, etc.
Is there any way to get this?
My previous code was:
def Generierung_Pendelrouten (Koordinaten):
d = {}
for i in range(1, len(Koordinaten)):
d['Pendelroute_{0}'.format(i)] = [0,i,0]
return d
With the result:
Pendelrouten:
{'Pendelroute_1': [0, 1, 0], 'Pendelroute_2': [0, 2, 0], 'Pendelroute_3': [0, 3, 0], 'Pendelroute_4': [0, 4, 0], 'Pendelroute_5': [0, 5, 0], 'Pendelroute_6': [0, 6, 0], 'Pendelroute_7': [0, 7, 0], 'Pendelroute_8': [0, 8, 0], 'Pendelroute_9': [0, 9, 0], 'Pendelroute_10': [0, 10, 0]}
But with the dictionary I can't then continue to work as desired.
My other idea was to work with a for loop:
for i in range (1,11):
route = []
route.append(0)
route.append(i)
route.append(0)
print(route)
But then you get only the last route [0, 10, 0] output. This is the format in which I want to have all 10 routes.
I want to return the max value of a matrix.
For example this is my matrix:
matrix = [[0, 1, 10, 0, 0], [0, 0, 6, 0, 1], [0, 1, 4, 0, 0]]
I want to return the max so here '10'
This is my code but I have an error:
max = 0
for i in range(len(matrix)+1):
for j in range(len(matrix[0])+1):
if matrix[i][j] > matrix[i+1][j+1]:
max = matrix[i][j]
print(max)
Thanks in advance
There are several issues with your code, I suggest you use the max function:
matrix = [[0, 1, 10, 0, 0], [0, 0, 6, 0, 1], [0, 1, 4, 0, 0]]
result = max(max(row) for row in matrix)
print(result)
Output
10
you can try this.
matrix = [[0, 1, 10, 0, 0], [0, 0, 6, 0, 1], [0, 1, 4, 0, 0]]
max1 = 0
for sub_list in matrix:
for item in sub_list:
if item>max1:
max1=item
Multiple ways to do it:
Fix your method. In Python, lists are zero-based so you need to only iterate from i = 0 to len(matrix) - 1. Doing for i in range(len(matrix)): does this for you. You don't need to do range(len(matrix) + 1)). Also, you should only replace the current maxval if the element you're looking at is greater than maxval.
So,
maxval = -9999999
for i in range(len(matrix)):
for j in range(len(matrix[i])):
if matrix[i][j] > maxval:
maxval = matrix[i][j]
print(maxval)
# Out: 10
Or, a more pythonic way is to iterate over the elements instead of accessing them through their indices
maxval = -9999999
for row in matrix:
for element in row:
if element > maxval:
maxval = element
# maxval: 10
Notice I use maxval instead of max so as not to shadow python's inbuilt max() function.
Use numpy (if you're already using it for other things). Like wim mentioned in their comment, a numpy array is a much better way to store matrices instead of lists of lists. Why? See this question
import numpy as np
matrix = [[0, 1, 10, 0, 0], [0, 0, 6, 0, 1], [0, 1, 4, 0, 0]]
maxval = np.max(matrix)
# maxval: 10
Iterate over rows, create a list of max values in each row. Then find the max of this list
matrix = [[0, 1, 10, 0, 0], [0, 0, 6, 0, 1], [0, 1, 4, 0, 0]]
rowmax = [max(row) for row in matrix]
maxval = max(rowmax)
# or in one line:
maxval = max(max(row) for row in matrix)
Use map. This is essentially the same as the previous method.
matrix = [[0, 1, 10, 0, 0], [0, 0, 6, 0, 1], [0, 1, 4, 0, 0]]
maxval = max(map(max, matrix))
Good evening! I have the following code which works when you write
python new.py -s 13 -p 5 on the command prompt.
What command prompt prints is :
[[1, [0], [0]], [1, [0], [0]], [1, [0], [0]], [1, [0]], [1, [0]]]
But I wanted:
[[1, 0, 0], [1, 0, 0], [1, 0, 0], [1, 0], [1, 0]]
How can I do this?
-s 12 is the length of the string and -p 7 the 1s.
Thank you!
My code sample :
import argparse
p = argparse.ArgumentParser()
p.add_argument("-pulses", help = "number of pulses", type = int)
p.add_argument("-slots", help = "length of the rythm", type = int)
args = p.parse_args()
slots = args.slots
pulses = args.pulses
pauses = slots - pulses
mod = slots % pulses
rhythm = []
if mod != 0:
i = 0
j = 0
temp = []
while i < pulses:
rhythm.append([1])
i = i + 1
while j < pauses:
rhythm.append([0])
j = j + 1
m = slots
n = pauses
while (rhythm[-1]==[0]):
if (n!=0):
step = m%n
hlp = n
m = n
n = step
i = 0
while (i<step):
rhythm[i].append(rhythm[-1])
rhythm.remove(rhythm[-1])
i = i + 1
print (rhythm)
Note: This is a mere copy&paste from the comment.
Check this out.
I haven't fully analyzed your code but I believe your problem resides in append(). Try to replace it for extend().
The Problem is this line
rhythm[i].append(rhythm[-1])
rhythm[-1] returns a list ([0] or [1]). So you must use extend instead of append.
rhythm[i].extend(rhythm[-1])
Python List
Woozy Coder definitively correctly answered this question.
More generally speaking about lists appending and extending:
dest_list.append(appended_item) appends an item to the list. Should the appended item be a list, this list will be appended as is, and becomes an additional item at the end of the destination list.
dest_list.extend(list_extension) extends a list with another list, every item of this other list being individually appended to the end of the destination list.
Your code seems overly complicated. I think the code below does what you're trying to do:
def rhythm_list(slots, pulses):
q, r = divmod(slots, pulses)
full = [1] + [0] * q
part = full[:-1]
return [full] * r + [part] * (pulses - r)
# Test
print(rhythm_list(13, 5))
print(rhythm_list(12, 7))
print(rhythm_list(12, 4))
output
[[1, 0, 0], [1, 0, 0], [1, 0, 0], [1, 0], [1, 0]]
[[1, 0], [1, 0], [1, 0], [1, 0], [1, 0], [1], [1]]
[[1, 0, 0], [1, 0, 0], [1, 0, 0], [1, 0, 0]]
Note that the output list contains duplicated references to the full and part lists, so if you do:
m = rhythm_list(12, 7)
m[0][0]=2
then m becomes:
[[2, 0], [2, 0], [2, 0], [2, 0], [2, 0], [1], [1]]
If this behaviour is undesirable, then change the last line of rhythm_list to
return [full[:] for _ in range(r)] + [part[:] for _ in range(pulses - r)]
What is wrong with the following program code, attempting to initialize a 4 x 4 matrix of integers? How should the initialization be done?
line = [0] * 4
matrix = [line, line, line, line]
Use a list comprehension:
>>> line = [[0]*4 for _ in xrange(4)]
>>> line
[[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
Don't do this though:
>>> line = [[0]*4]*4
>>> line
[[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
The output looks same, but the problem here is all inner lists are actually the same object repeated 4 times:
>>> [id(x) for x in line]
[156931756, 156931756, 156931756, 156931756]
So, changing one of them is going to affect all:
>>> line[2][0] = 10
>>> line
[[10, 0, 0, 0], [10, 0, 0, 0], [10, 0, 0, 0], [10, 0, 0, 0]]
Same thing is applicable to your code:
>>> line = [0] * 4
>>> matrix = [line, line, line, line]
>>> [id(x) for x in matrix]
[158521804, 158521804, 158521804, 158521804]
If line contains only immutable object then you can change your code do:
>>> matrix = [line[:] for _ in xrange(4)]
But, if line contains mutable objects itself, then you'd have to use either copy.deepcopy or better create a new line object inside the list comprehension.
you could use numpy for that if you want to perform computations on your matrix
import numpy as np
zeros = np.zeros([4,4])
The problem is:
>>> line = [0] * 4
>>> matrix = [line, line, line, line]
>>> matrix[0][0] = 5
>>> matrix
[[5, 0, 0, 0], [5, 0, 0, 0], [5, 0, 0, 0], [5, 0, 0, 0]]
You have and array of references to the same vector.
What is wrong here that you create a list of 4 references to line list. If you change any of sub-lists or line itself, you affect all sub-lists of matrix, since they (sub-lists) are essentially the same list
Here is a little demonstration
In [108]: line = [0] * 4
In [109]: matrix = [line, line, line, line]
In [110]: line[1]=2
In [111]: matrix
Out[111]: [[0, 2, 0, 0], [0, 2, 0, 0], [0, 2, 0, 0], [0, 2, 0, 0]]
In [112]: matrix[1][3] = 4
In [113]: matrix
Out[113]: [[0, 2, 0, 4], [0, 2, 0, 4], [0, 2, 0, 4], [0, 2, 0, 4]]
In [114]: for row in matrix:
.....: print id(row)
.....:
3065415660
3065415660
3065415660
3065415660
You need to do this:
matrix = [[0 for row in range(4)] for col in range(4)]
Your code works ok, but it's not flexible one. So, if you want to create 5*5 martix you have explicitly add more line objects to matrix init code. So, using for + xrange generators looks more suitable.
Also, not sure about case of using this matrix - but be aware about using the same object (list) as matrix line. So, if you change it's element - it would be modified in all rows:
matrix[0][0] = 'new value'
print matrix
[['new value', 0, 0, 0], ['new value', 0, 0, 0], ['new value', 0, 0, 0], ['new value', 0, 0, 0]]