Python list generator not working as intended - python

First of all, I'm making a game in which the map is a list of lists:
P1.Cmap = [
['0,'0',0'],
['0,'0',0'],
['0,'0',0'],
]
and I have a function to print it:
def render(): #render the map to player
P1.Cmap[P1.y][P1.x] = P1.char
j = 40 - len(P1.Cmap)
p = int(j/2)
l = len(P1.Cmap[0])
print('\n' * p)
print('-' * l)
for r in P1.Cmap:
print(''.join(r))
print('\n' * p)
where P1 is the player object and char is the character to represent it (X)
and I also made a function to generate a map with the given parameters:
def newMap():
Nmn = input('What is the name of the map? ')
NmSx = input('What is the size you want?(X) ')
NmSy = input('What is the size you want?(Y) ')
Row = []
Map = []
for r in range(int(NmSx)):
Row.append('0')
for c in range(int(NmSy)):
Map.append(Row)
P1.Cmap = Map
print(P1.Cmap)
but when I set the player X and Y to be P1.x = 1, P1.y = 0 and I use the function to generate the map, it actually prints:
0X0
0X0
0X0
instead of what it "should" (When I make the map like the first code block above):
0X0
000
000
with that I thought that the problem is not in the render() but it is in the newMap(), but I can't seem to find it, any ideas?

You are creating P1.Cmap in the following way:
Row = []
Map = []
for r in range(int(NmSx)):
Row.append('0')
for c in range(int(NmSy)):
Map.append(Row)
P1.Cmap = Map
However, this makes Map equal to [Row, Row, Row], that is, Row is always referencing the same list you created above with Row = [], therefore any time you modify Row the changes will be reflected in Map in all three "rows", since each "row" is Row!.
Instead, try something like :
X = int(NmSx)
Y = int(NmSy)
Map = [['0' for _ in range(X)] for _ in range(Y)]

Related

How to create coordinates for nodes of graph

I have a list that has strings separated by commas. The values of each string are nothing but the navigation steps/action of the same procedure done by different users. I want to create coordinates for these steps/actions and store them for creating graph. Each unique steps/actions
will have one coordinate. My idea is I will consider a string with more steps first. I will assign them coordinates ranging from (1,0) to (n,0). Here first string will have 'y' as 0 saying all the actions will be in one layer. When i check for steps/actions in second string, if there are any missing ones i will assign them (1,1) to (n,1). So on... Care has to be taken that if first steps/actions of one string falls in between of another bigger string, the coordinates should be after that.
This sounds confusing, but in simple terms, i want to create coordinates for user flow of a website.
Assume list,
A = ['A___O___B___C___D___E___F___G___H___I___J___K___L___M___N',
'A___O___B___C___E___D___F___G___H___I___J___K___L___M___N',
'A___B___C___D___E___F___G___H___I___J___K___L___M___N',
'A___B___C___E___D___F___G___H___I___J___K___L___M___N',
'A___Q___C___D___E___F___G___H___I___J___K___L___M___N',
'E___P___F___G___H___I___J___K___L___M___N']
I started below code, but it is getting complicated. Any help is appreciated.
A1 = [i.split('___') for i in A]
# A1.sort(key=len, reverse=True)
A1 = sorted(A1, reverse=True)
if len(A1)>1:
Actions = {}
horizontalVal = {}
verticalVal = {}
restActions = []
for i in A1:
for j in i[1:]:
restActions.append(j)
for i in range (len(A1)):
if A1[i][0] not in restActions and A1[i][0] not in Actions.keys():
Actions[A1[i][0]] = [i,0]
horizontalVal[A1[i][0]] = i
verticalVal[A1[i][0]] = 0
unmarkedActions = []
for i in range(len(sortedLen)):
currLen = sortedLen[i]
for j in range(len(A1)):
if len(A1[j]) == currLen:
if j == 0:
for k in range(len(A1[j])):
currK = A1[j][k]
if currK not in Actions.keys():
Actions[currK] = [k,0]
horizontalVal[currK] = k
verticalVal[currK] = 0
else:
currHori = []
print(A1[j])
for k in range(len(A1[j])):
currK = A1[j][k]
.
. to be continued

Is there a way to assign automatic values to a 2D array in Python with a specific pattern without filling the whole array with just one value?

I'm trying to create a really basic snake-like console game just to test Python's functionality, yet I'm having issues with an algorithm I created for setting up the game map. I need the map borders to be set up as '#' and the map body as a space ' ' but for some reason the whole map is being shown as hashes, even after printing out the results in the decisive if function. Here's the code:
class GameMap:
def __init__(self):
self.border_icon = '#'
self.body_icon = ' '
self.x_size = 0
self.y_size = 0
self.map_grid = []
def create_grid(self, map_size):
if map_size == 1:
self.x_size = 40
self.y_size = 20
elif map_size == 2:
self.x_size = 80
self.y_size = 40
else:
self.x_size = 120
self.y_size = 60
self.map_grid = [[None]*self.x_size]*self.y_size
for row in range(self.y_size):
for column in range(self.x_size):
if row==0 or row==self.y_size-1 or column==0 or column==self.x_size-1:
print('set: '+self.border_icon)
self.map_grid[row][column] = self.border_icon
else:
print('set: '+self.body_icon)
self.map_grid[row][column] = self.body_icon
def setup(self, map_type):
map_templates = {
1: 'Small Map (40x20)',
2: 'Medium Map (80x40)',
3: 'Big Map (120x60)'
}
if map_type not in map_templates:
print('Invalid map type, starting a game with the default configuration...')
map_type = 1
print('Starting game: '+map_templates.get(map_type,'Invalid map type'))
self.create_grid(map_type)
This is the map class, in order to access it I just create a map object and call for the setup.
The issue is that whenever I display the matrix, the whole map is filled with '#' and no spaces whatsoever. Is there a reason for this?
The problem is not in the For-loop, but, issue is in this line:
self.map_grid = [[None]*self.x_size]*self.y_size
Say your self.x_size is 5 and self.y_size is 10, then, this line evaluates to this:
[[None, None, None, None, None]] * 10
At this very moment you have a list having reference to inner list (which is its only element). Now, if you multiply with self.y_size, you are just getting 9 (in this case) more references to inner list. This is a very common misunderstanding among new Python developers.
There are 2 possible solutions for your problem:
Nested List Comprehension:
self.map_grid = [[None for _ in range(self.x_size)] for _ in range(self.y_size)]
OR
self.map_grid = [[None] * self.x_size for _ in range(self.y_size)]
I just changed that block:
for row in range(self.y_size):
for column in range(self.x_size):
if row==0 or row==self.y_size-1 or column==0 or column==self.x_size-1:
print('set: '+self.border_icon)
self.map_grid[row][column] = self.border_icon
else:
print('set: '+self.body_icon)
self.map_grid[row][column] = self.body_icon
and I think it works
row=0
column=0
while(row<=self.x_size):
while(column<=self.y_size):
if row==0 or row==self.x_size:
print("#",end="")
elif column==0 or column==self.y_size:
print("#",end="")
else:
print(" ",end="")
column=column+1
column=0
print()
row=row+1

Problems with the zip function: lists that seem not iterable

I'm having some troubles trying to use four lists with the zip function.
In particular, I'm getting the following error at line 36:
TypeError: zip argument #3 must support iteration
I've already read that it happens with not iterable objects, but I'm using it on two lists! And if I try use the zip only on the first 2 lists it works perfectly: I have problems only with the last two.
Someone has ideas on how to solve that? Many thanks!
import numpy
#setting initial values
R = 330
C = 0.1
f_T = 1/(2*numpy.pi*R*C)
w_T = 2*numpy.pi*f_T
n = 10
T = 1
w = (2*numpy.pi)/T
t = numpy.linspace(-2, 2, 100)
#making the lists c_k, w_k, a_k, phi_k
c_karray = []
w_karray = []
A_karray = []
phi_karray = []
#populating the lists
for k in range(1, n, 2):
c_k = 2/(k*numpy.pi)
w_k = k*w
A_k = 1/(numpy.sqrt(1+(w_k)**2))
phi_k = numpy.arctan(-w_k)
c_karray.append(c_k)
w_karray.append(w_k)
A_karray.append(A_k)
phi_karray.append(phi_k)
#making the function w(t)
w = []
#doing the sum for each t and populate w(t)
for i in t:
w_i = ([(A_k*c_k*numpy.sin(w_k*i+phi_k)) for c_k, w_k, A_k, phi_k in zip(c_karray, w_karray, A_k, phi_k)])
w.append(sum(w_i)
Probably you mistyped the last 2 elements in zip. They should be A_karray and phi_karray, because phi_k and A_k are single values.
My result for w is:
[-0.11741034896740517,
-0.099189027720991918,
-0.073206290274556718,
...
-0.089754003567358978,
-0.10828235682188027,
-0.1174103489674052]
HTH,
Germán.
I believe you want zip(c_karray, w_karray, A_karray, phi_karray). Additionally, you should produce this once, not each iteration of the for the loop.
Furthermore, you are not really making use of numpy. Try this instead of your loops.
d = numpy.arange(1, n, 2)
c_karray = 2/(d*numpy.pi)
w_karray = d*w
A_karray = 1/(numpy.sqrt(1+(w_karray)**2))
phi_karray = numpy.arctan(-w_karray)
w = (A_karray*c_karray*numpy.sin(w_karray*t[:,None]+phi_karray)).sum(axis=-1)

Analog of templates in Python

As part of some simulations I'm running I need to output the cumulative distribution of the output of some algorithms:
tests = []
numtests = 100
for i in range(0, numtests):
#random
zeros = [0] * 1024
ones = [1] * 10
#ones = [randint(0,1023) for _ in range(0,10)]
input = zeros + ones
shuffle(input)
tests.append(HGBSA(input,10))
count = [x[0] for x in tests]
found = [x[1] for x in tests]
found.sort()
num = Counter(found)
freqs = [x for x in num.values()]
cumsum = [sum(item for item in freqs[0:rank+1]) for rank in range(len(freqs))]
normcumsum = [float(x)/numtests for x in cumsum]
print(freqs)
print(cumsum)
print(normcumsum)
print(sorted(num.keys()))
figure(0)
plt.plot(sorted(num.keys()), normcumsum)
plt.xlim(0,100)
plt.show()
As the above code shows, I'm running my algorithm 100 times with randomly generated input and then creating a cumulative distribution from the results.
I want to do a similar thing with other algorithms, and in c++ I could write a template class/template function which took a (pointer to a) method as am argument.
I'd like to ask if there is a way in python to create a function/class which produces the output I want, but takes a function as an input, so I avoid duplicating code all over the place.
This is simple to do in Python. You can pass functions (or classes) around like anything else.
def run_test(test_function):
tests = []
numtests = 100
for i in range(0, numtests):
#random
zeros = [0] * 1024
ones = [1] * 10
#ones = [randint(0,1023) for _ in range(0,10)]
input = zeros + ones
shuffle(input)
tests.append(test_function(input,10))
count = [x[0] for x in tests]
found = [x[1] for x in tests]
found.sort()
num = Counter(found)
freqs = [x for x in num.values()]
cumsum = [sum(item for item in freqs[0:rank+1]) for rank in range(len(freqs))]
normcumsum = [float(x)/numtests for x in cumsum]
print(freqs)
print(cumsum)
print(normcumsum)
print(sorted(num.keys()))
figure(0)
plt.plot(sorted(num.keys()), normcumsum)
plt.xlim(0,100)
plt.show()
run_test(HGBSA)
run_test(SOME_OTHER_FUNCTION)
I am not sure that i understand the question, but sounds like you want to pass a function as function argument? You can do that right of the bat in python as everything is passed by reference and nothing stops you from passing a reference to a function as an argument.

Can a python list hold a multi-dimentional array as its element?

I am trying to do image processing using python.
I try to create a list which holds numpy.ndarrays.
My code looks like this,
def Minimum_Close(Shade_Corrected_Image, Size):
uint32_Shade_Corrected_Image = pymorph.to_int32(Shade_Corrected_Image)
Angles = []
[Row, Column] = Shade_Corrected_Image.shape
Angles = [i*15 for i in range(12)]
Image_Close = [0 for x in range(len(Angles))]
Image_Closing = numpy.zeros((Row, Column))
for s in range(len(Angles)):
Struct_Element = pymorph.seline(Size, Angles[s])
Image_Closing = pymorph.close(uint32_Shade_Corrected_Image,Struct_Element )
Image_Close[s] = Image_Closing
Min_Close_Image = numpy.zeros(Shade_Corrected_Image.shape)
temp_array = [][]
Temp_Cell = numpy.zeros((Row, Column))
for r in range (1, Row):
for c in range(1,Column):
for Cell in Image_Close:
Temp_Cell = Image_Close[Cell]
temp_array[Cell] = Temp_Cell[r][c]
Min_Close_Image[r][c] = min(temp_array)
Min_Close_Image = Min_Close_Image - Shade_Corrected_Image
return Min_Close_Image
While running this code I'm getting error:
Temp_Cell = Image_Close[Cell]
TypeError: only integer arrays with one element can be converted to an index
How can I make a data structure which holds different multi-dimensional arrays and then traverse through it??
Making a list of arrays is not necessary when you're using numpy.
I suggest rewriting the whole function like this:
def Minimum_Close(shade_corrected_image, size):
uint32_shade_corrected_image = pymorph.to_int32(shade_corrected_image)
angles = np.arange(12) * 15
def pymorph_op(angle):
struct_element = pymorph.seline(size, angle)
return pymorph.close(uint32_shade_corrected_image, struct_element)
image_close = np.dstack(pymorph_op(a) for a in angles)
min_close_image = np.min(image_close, axis=-1) - shade_corrected_image
return min_close_image
I lower cased variable names so that they stop getting highlighted as classes.
What about:
for cnt,Cell in enumerate(Image_Close):
Temp_Cell = Image_Close[cnt]

Categories

Resources