Two-Dimensional Arrays not updating correctly in python 3 - python

So I am trying to create a simple world generation using code that I currently understand. I am doing this by creating a 2-dimensional array using 0's as nothing and 1's as a drawing function. I first create a blank world using input variables and then I plan to update the array using a generation script. However when trying to update world[0][x] it updates every item at that "x" location throughout every single list
Here is my code:
import random
worldHeight = 10 #int(input("What is the world height? "))
worldLength = 5 #int(input("What is the world length? "))
terrainHeight = 5 #int(input("What is the terrain height? "))
step = 2 #int(input("What is the step? "))
world = []
worldBlankRow = []
def createBlank():
global worldLength, worldHeight, world, worldBlankRow
for n in range(0,worldHeight):
worldBlankRow.append(0)
for n in range(0,worldLength):
world.append(worldBlankRow)
print(world)
def generate():
global world, worldHeight, worldLength,terrainHeight
counter=0
#randomStep = random.randint(-(step),step)
#while counter <= worldLength:
for x in range(worldHeight-terrainHeight,worldHeight):
world[0][x] = 1
print(world)
#counter=counter+1
#print(counter)
createBlank()
generate()
and here is my output so you can see what is going wrong:
[[0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]
[[0, 0, 0, 0, 0, 1, 0, 0, 0, 0], [0, 0, 0, 0, 0, 1, 0, 0, 0, 0], [0, 0, 0, 0, 0, 1, 0, 0, 0, 0], [0, 0, 0, 0, 0, 1, 0, 0, 0, 0], [0, 0, 0, 0, 0, 1, 0, 0, 0, 0]]
[[0, 0, 0, 0, 0, 1, 1, 0, 0, 0], [0, 0, 0, 0, 0, 1, 1, 0, 0, 0], [0, 0, 0, 0, 0, 1, 1, 0, 0, 0], [0, 0, 0, 0, 0, 1, 1, 0, 0, 0], [0, 0, 0, 0, 0, 1, 1, 0, 0, 0]]
[[0, 0, 0, 0, 0, 1, 1, 1, 0, 0], [0, 0, 0, 0, 0, 1, 1, 1, 0, 0], [0, 0, 0, 0, 0, 1, 1, 1, 0, 0], [0, 0, 0, 0, 0, 1, 1, 1, 0, 0], [0, 0, 0, 0, 0, 1, 1, 1, 0, 0]]
[[0, 0, 0, 0, 0, 1, 1, 1, 1, 0], [0, 0, 0, 0, 0, 1, 1, 1, 1, 0], [0, 0, 0, 0, 0, 1, 1, 1, 1, 0], [0, 0, 0, 0, 0, 1, 1, 1, 1, 0], [0, 0, 0, 0, 0, 1, 1, 1, 1, 0]]
[[0, 0, 0, 0, 0, 1, 1, 1, 1, 1], [0, 0, 0, 0, 0, 1, 1, 1, 1, 1], [0, 0, 0, 0, 0, 1, 1, 1, 1, 1], [0, 0, 0, 0, 0, 1, 1, 1, 1, 1], [0, 0, 0, 0, 0, 1, 1, 1, 1, 1]]
as you can see every list is updating where i want to generate one, then the next and then the next.

The problem is that you append worldBlankRow to world. Now this means that the exact same object is appended many times to world. Later, when you change one element of world, you change them all, because they are all really pointing to the same worldBlankRow. You need a separate copy for each. Try:
import random
import copy
worldHeight = 10 #int(input("What is the world height? "))
worldLength = 5 #int(input("What is the world length? "))
terrainHeight = 5 #int(input("What is the terrain height? "))
step = 2 #int(input("What is the step? "))
world = []
worldBlankRow = []
def createBlank():
global worldLength, worldHeight, world, worldBlankRow
for n in range(0,worldHeight):
worldBlankRow.append(0)
for n in range(0,worldLength):
world.append(copy.copy(worldBlankRow))
print(world)
def generate():
global world, worldHeight, worldLength,terrainHeight
counter=0
#randomStep = random.randint(-(step),step)
#while counter <= worldLength:
for x in range(worldHeight-terrainHeight,worldHeight):
world[0][x] = 1
print(world)
#counter=counter+1
#print(counter)
createBlank()
generate()

Related

Creating arrays with a loop (Python)

I am trying to create several arrays from a big array that I have. What I mean is:
data = [[0, 1, 0, 0, 0, 0, 0, 1, 0, 0], [0, 0, 1, 0, 0, 1, 0, 0, 0, 0],
[0, 1, 1, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 1, 0, 0, 0, 0, 1],
[0, 0, 1, 1, 0, 0, 0, 0, 0,1], [0, 0, 0, 0, 1, 1, 0, 0, 0, 0],
[1, 0, 0, 0, 0, 0, 0, 1, 0, 0], [0, 1, 0, 0, 0, 1, 0, 0, 0, 0],
[0, 0, 0, 0, 1, 0, 0, 0, 1, 0]]
I want to create 10 different arrays - using the 10 data's columns - with different names.
data1 = [0, 0, 0, 1, 0, 0, 1, 0, 0],
data2 = [1, 0, 1, 0, 0, 0, 0, 1, 0], and so on
I found a close solution here - Also I take the example data from there - However, when I tried the solution suggested:
for d in xrange(0,9):
exec 'x%s = data[:,%s]' %(d,d-1)
A error message appears:
exec(code_obj, self.user_global_ns, self.user_ns)
File "", line 2, in
exec ('x%s = data[:,%s]') %(d,d-1)
File "", line 1
x%s = data[:,%s]
^
SyntaxError: invalid syntax
Please, any comments will be highly appreciated. Regards
Use numpy array index:
data = [[0, 1, 0, 0, 0, 0, 0, 1, 0, 0], [0, 0, 1, 0, 0, 1, 0, 0, 0, 0],
[0, 1, 1, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 1, 0, 0, 0, 0, 1],
[0, 0, 1, 1, 0, 0, 0, 0, 0,1], [0, 0, 0, 0, 1, 1, 0, 0, 0, 0],
[1, 0, 0, 0, 0, 0, 0, 1, 0, 0], [0, 1, 0, 0, 0, 1, 0, 0, 0, 0],
[0, 0, 0, 0, 1, 0, 0, 0, 1, 0]]
d = np.array(data)
d[:, 0]
#array([0, 0, 0, 1, 0, 0, 1, 0, 0])
d[:, 1]
#array([1, 0, 1, 0, 0, 0, 0, 1, 0])
etc...
d[:, 9]
#array([0, 0, 1, 1, 1, 0, 0, 0, 0])
If you must, then dictionaries are the way to go:
val = {i:d[:,i] for i in range(d.shape[1])}
To access the arrays:
val[0]
#array([0, 0, 0, 1, 0, 0, 1, 0, 0])
...
val[9]
#array([0, 0, 1, 1, 1, 0, 0, 0, 0])
Use the following code (it is also more readable -- for python 3.x) if you really want to create dynamic variables:
for d in range(0,9):
# exec 'x%s = data[:,%s]' %(d,d-1)
exec(f"data{d} = {data[d]}" )
Either use numpy array as shown by scott boston above or use dictionary like this:
a = {}
for i in range(0,9):
a[i] = data[i][:]
Output:
{0: [0, 1, 0, 0, 0, 0, 0, 1, 0, 0],
1: [0, 0, 1, 0, 0, 1, 0, 0, 0, 0],
2: [0, 1, 1, 0, 0, 0, 0, 0, 0, 1],...
I don't see the proper indentation in your for loop.
I suggest you don't use %s for the second argument (string) but rather %d (number) since you need a number to do the indexing of your array.

optimizing my Battleship field validator 4x4, and fix error

I'm a new to stackoverflow, recently I'm trying to solve a problem from codewar with Python 3x and it's about validating battleship location on a 10x10 grid. I passed 33 tests and failed 17 one, which is pretty bad, plus I sometimes get timeout error, so I figured there must be something wrong with my code, I'm open to listen to any opinion, can somebody help me?
def validate_battlefield(field):
# important list comprehension !!!! to add element in a sublist infront and behind
field = [[0] + k + [0] for k in field]
extended_field = [[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]
extended_field.extend(field)
extended_field.extend([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]])
field = extended_field
# print(extended_field)
list_of_battleship = []
for h in range(1, 11):
for w in range(1, 11):
if field[h][w] == 1:
m, n = h, w
print("*****************")
print(h, n)
length_ship = 1
field[m][n] = -1
if field[h + 1][w] == 0 and field[h][w + 1] == 0:
list_of_battleship.append(1)
break
while field[m][n + 1] + field[m + 1][n] + field[m][n-1] != 2:
if field[m][n + 1] == 1:
print(m, n + 1)
length_ship += 1
field[m][n + 1] = -1
n += 1
if field[m][n + 1] == 0:
list_of_battleship.append(length_ship)
break
if field[m + 1][n] == 1:
print(m + 1, n)
length_ship += 1
field[m + 1][n] = -1
m += 1
if field[m + 1][n] == 0:
list_of_battleship.append(length_ship)
break
list_of_battleship.sort()
if list_of_battleship == [1, 1, 1, 1, 2, 2, 2, 3, 3, 4]:
return True
else:
return False
I can't get the following validation right, I really don't know where went wrong
print(validate_battlefield([
[1, 0, 0, 0, 0, 1, 1, 0, 0, 0],
[1, 0, 1, 0, 0, 0, 0, 0, 1, 0],
[1, 0, 1, 0, 1, 1, 1, 0, 1, 0],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 1, 0],
[0, 0, 0, 0, 1, 1, 1, 0, 0, 0],
[0, 1, 0, 0, 0, 0, 0, 0, 1, 0],
[0, 0, 0, 1, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 1, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],]
))
print(validate_battlefield(
[
[0, 0, 0, 0, 1, 1, 1, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
[0, 0, 0, 0, 0, 0, 0, 1, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 1, 0, 0, 1, 1, 1, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[1, 0, 0, 0, 0, 1, 1, 0, 0, 0],
[0, 0, 0, 1, 0, 0, 0, 0, 0, 1],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
[0, 0, 0, 1, 1, 1, 0, 0, 0, 0]
]
))

eroding several layers of an array

I'm having trouble understanding scipy's binary_erosion function.
from scipy.ndimage import binary_erosion
a = np.zeros([12,12])
a[1:11,1:11]=1
binary_erosion(a).astype(int)
this removes the outermost edges, but what if I want to remove the second layer as well? I know I should probably use the structure option, but I don't understand how it works and could not find enough examples that explain it properly
Use the iterations option to have it repeat n times (remove additional layers): [source]
iterations : int, optional
The erosion is repeated iterations times (one, by default). If iterations is less than 1, the erosion is repeated until the result does not change anymore.
So yours:
array([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0],
[0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0],
[0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0],
[0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0],
[0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0],
[0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0],
[0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0],
[0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]])
And with the iterations option set to 2, you'll notice an additional layer has been reduced.
>>> binary_erosion(a, iterations=2).astype(int)
array([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0],
[0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0],
[0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0],
[0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0],
[0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0],
[0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]])
Since you asked in a comment, the structure can be used to determine how much to remove for each iteration. There is a good breakdown here of what that means.
This is the structuring element used for erosion. Meaning that if this were a 3x3 square, as it moved around the edge, the pixels that are completely covered will get removed, and the ones that are only partially covered will stay.
Also take a look at this medium post which has hand drawn a bunch of examples for how this works and breaks it down even further.

Drawing a directed graph using a link matrix with networkx

I am working on pagerank for a school project, and i have a matrix where the row "i" represent the links from the site j (line) to the site i. (If it is still unclear i'll explain more).
The current part is:
Z=[[0,1,1,1,1,0,1,0,0,0,0,0,0,0],[1,0,0,0,1,0,0,0,0,0,0,0,0,0], [1,1,0,0,0,0,0,0,0,0,0,0,0,0],[1,0,1,0,0,0,0,0,0,0,0,0,0,0],[1,0,0,1,0,0,0,0,0,0,0,0,0,0],[1,0,0,0,0,0,0,1,0,1,0,0,0,0],[0,0,0,0,0,1,0,0,0,0,0,0,0,0],[0,0,0,0,0,1,1,0,1,0,0,0,0,0],[0,0,0,0,0,1,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,1,0,1,1,1,1],[0,0,0,0,0,0,0,0,0,1,0,0,0,1],[0,0,0,0,0,0,0,0,0,1,1,0,0,0],[0,0,0,0,0,0,0,0,0,1,0,1,0,0],[0,0,0,0,0,0,0,0,0,1,0,0,1,0]]
A=np.matrix(Z)
G=nx.from_numpy_matrix(A,create_using=nx.MultiDiGraph())
pos=nx.circular_layout(G)
labels={}
for i in range (N):
labels[i]=i+1
nx.draw_circular(G)
nx.draw_networkx_labels(G,pos,labels,font_size=15)
The problem i have is that the labels are not where they are supposed to be, it seems that networkx is just placing them clockwise...
Also, how could i easily direct the graph, so that a link from j to i won't be from i to j?
Thanks!
import numpy as np
import matplotlib.pyplot as plt
import networkx as nx
Z = [[0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0],
[1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0]]
G = nx.from_numpy_matrix(np.array(Z), create_using=nx.MultiDiGraph())
pos = nx.circular_layout(G)
nx.draw_circular(G)
labels = {i : i + 1 for i in G.nodes()}
nx.draw_networkx_labels(G, pos, labels, font_size=15)
plt.show()
yields
This result appears correct to me. Notice, for example, that the node labeled 1 has directed edges pointing to 2, 3, 4, 5 and 7. This corresponds to the ones on the first row in the array, Z[0]:
[0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0]
since the first row corresponds to node 1, and the ones in this row occur in the columns corresponding to nodes 2, 3, 4, 5 and 7.

Longest Common Sequence -Index Error

I am trying to find the LCS between two sequences: TACGCTGGTACTGGCAT and AGCTGGTCAGAA. I want my answer to output as a matrix so that I can backtrack which sequence is common (GCTGGT). When I use my code below, I am getting the following error. IndexError: list index out of range. How can I avoid this error in my code below?
def LCS(x, y):
m = len(x)
n = len(y)
C = []
for i in range(m):
for j in range(n):
if x[i] == y[j]:
C[i][j] == C[i-1][j-1] + 1
else:
C[i][j] == 0
return C
x = "TACGCTGGTACTGGCAT"
y = "AGCTGGTCAGAA"
m = len(x)
n = len(y)
C = LCS(x, y)
print C
You need to append to your list, because the index [i][j] does not exist yet.
def LCS(x, y):
m = len(x)
n = len(y)
C = []
for i in range(m):
C.append([]) # append a blank list at index [i]
for j in range(n):
if x[i] == y[j]:
C[i].append(C[i-1][j-1] + 1) # append current element to [i]
else:
C[i].append(0)
return C
Testing
x = "TACGCTGGTACTGGCAT"
y = "AGCTGGTCAGAA"
LCS(x,y)
Output
[[0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0],
[1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1],
[0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0],
[0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0],
[0, 0, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0],
[0, 0, 0, 3, 0, 0, 1, 0, 0, 0, 0, 0],
[0, 1, 0, 0, 4, 1, 0, 0, 0, 1, 0, 0],
[0, 1, 0, 0, 1, 5, 0, 0, 0, 1, 0, 0],
[0, 0, 0, 1, 0, 0, 6, 0, 0, 0, 0, 0],
[1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1],
[0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0],
[0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 0, 0],
[0, 1, 0, 0, 3, 1, 0, 0, 0, 1, 0, 0],
[0, 1, 0, 0, 1, 4, 0, 0, 0, 1, 0, 0],
[0, 0, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0],
[1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 1, 1],
[0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0]]

Categories