How could I distribute obstacles to my grid without writing them manually? - python

I'm working on A star algorithm and as my code below shown the gird is written manually and I'm thinking to make a grid with 100* 100 size. So, it will be so awful to write them manually. I need to put my starting point at (0,0) location and my goal point at (99,99) location.
I'm trying to make the grid with this line below
grid1 = [[0 for i in range(100)]for j in range(100)]
But how could I assign obstacles to this grid randomly or not randomly without touching the location of starting point and goal point?
This is below my code:
from __future__ import print_function
import random
grid = [[0, 1, 0, 0, 0, 0],
[0, 1, 0, 0, 0, 0],#0 are free path whereas 1's are obstacles
[0, 1, 0, 0, 0, 0],
[0, 1, 0, 0, 1, 0],
[0, 0, 0, 0, 1, 0]]
'''
heuristic = [[9, 8, 7, 6, 5, 4],
[8, 7, 6, 5, 4, 3],
[7, 6, 5, 4, 3, 2],
[6, 5, 4, 3, 2, 1],
[5, 4, 3, 2, 1, 0]]'''
init = [0, 0]
goal = [len(grid)-1, len(grid[0])-1] #all coordinates are given in format [y,x]
cost = 1
drone_h = 60
#the cost map which pushes the path closer to the goal
heuristic = [[0 for row in range(len(grid[0]))] for col in range(len(grid))]
for i in range(len(grid)):
for j in range(len(grid[0])):
heuristic[i][j] = abs(i - goal[0]) + abs(j - goal[1])
#if grid[i][j] == 1:
#heuristic[i][j] = 99 #added extra penalty in the heuristic map
print(heuristic)
elevation = [[0 for row in range(len(grid[0]))] for col in range(len(grid))]
for i in range(len(grid)):
for j in range(len(grid[0])):
if grid[i][j] == 1:
elevation[i][j] = random.randint(1,100)
else:
elevation[i][j] = 0
#the actions we can take
delta = [[-1, 0 ], # go up
[ 0, -1], # go left
[ 1, 0 ], # go down
[ 0, 1 ]] # go right
#function to search the path
def search(grid,init,goal,cost,heuristic):
closed = [[0 for col in range(len(grid[0]))] for row in range(len(grid))]# the referrence grid
closed[init[0]][init[1]] = 1
action = [[0 for col in range(len(grid[0]))] for row in range(len(grid))]#the action grid
x = init[0]
y = init[1]
g = 0
f = g + heuristic[init[0]][init[0]] + elevation[init[0]][init[0]]
cell = [[f, g, x, y]]
found = False # flag that is set when search is complete
resign = False # flag set if we can't find expand
while not found and not resign:
if len(cell) == 0:
resign = True
return "FAIL"
else:
cell.sort()#to choose the least costliest action so as to move closer to the goal
cell.reverse()
next = cell.pop()
x = next[2]
y = next[3]
g = next[1]
f = next[0]
if x == goal[0] and y == goal[1]:
found = True
else:
for i in range(len(delta)):#to try out different valid actions
x2 = x + delta[i][0]
y2 = y + delta[i][1]
if x2 >= 0 and x2 < len(grid) and y2 >=0 and y2 < len(grid[0]):
if closed[x2][y2] == 0 and grid[x2][y2] == 0 and elevation[x2][y2] < drone_h :
g2 = g + cost
f2 = g2 + heuristic[x2][y2] + elevation[x2][y2]
cell.append([f2, g2, x2, y2])
closed[x2][y2] = 1
action[x2][y2] = i
invpath = []
x = goal[0]
y = goal[1]
invpath.append([x, y])#we get the reverse path from here
while x != init[0] or y != init[1]:
x2 = x - delta[action[x][y]][0]
y2 = y - delta[action[x][y]][1]
x = x2
y = y2
invpath.append([x, y])
path = []
for i in range(len(invpath)):
path.append(invpath[len(invpath) - 1 - i])
print("ACTION MAP")
for i in range(len(action)):
print(action[i])
return path
a = search(grid,init,goal,cost,heuristic)
for i in range(len(a)):
print(a[i])

You could assign the grid randomly and afterwards make sure both starting and end point don't contain obstacles. For neighboring fields you could just do the same as for those two.
import random
grid1 = [[random.randint(0,1) for i in range(100)]for j in range(100)]
# clear starting and end point of potential obstacles
grid1[0][0] = 0
grid1[99][99] = 0

Related

Obtaining the Respective Token

I am creating python code for the Timed Event Graph as in the following screenshot.
The rule for the combination of A6 is as follows in order to get the respective p or c.
For example: p_4 , c_1 , c_2
Here is the respective values from the respective list of p and c.
p_4 = 50
c_1 = 7
c_2 = 140
Then, according to the rule, the combination for the token is z_4 , (m_1 - z_1) , z_2.
Here is the calculation from the respective list of m and z.
z_4 = 0
m_1 - z_1 = 3 - 2 = 1
z_2 = 1
The set of p and c as well as m and z are parameters.
All of the possible combination is listed on the Table 1 under the Timed Event Graph.
Then, I created code as follows.
import numpy as np
from itertools import combinations
m = [3,4,2,1]
z = [2,1,2,0]
p = [100,120,3,50]
c = [7,140,80,220]
n = len(m)
S = np.arange(1,n+1)
comb = combinations(S, 5)
only_odd = [num for num in S if num % 2 == 1]
len_A = [num for num in only_odd if num !=1]
storage_j = []
for x in len_A:
comb = combinations(S,x)
for j in list(comb):
storage_j.append(j)
storage_i = []
for A_j in storage_j:
temp_i = []
for j in A_j:
if j ==1:
i = n-1 #minus 1 to adjust into the python index
if j != 1:
i = j-1-1 #minus 1 to adjust into the python index
temp_i.append(i)
storage_i.append(temp_i)
The storage_i indicates the respective index for each combination in Table 1.
storage_i = [[3, 0, 1], [3, 0, 2], [3, 1, 2], [0, 1, 2]]
Then, I created the code for A6 in Table 1 as follows.
final_A6 = []
for ida in storage_i:
temp = []
for i in ida:
if i == (n-1):
AC = ((i+1)%2)*c[i] + (1-((i+1)%2))*p[i] #np.remainder(i,2) #AC for R6
if i != (n-1):
if (len(temp)==0) or (len(temp)%2 ==0):
AC = ((i+1)%2)*p[i] + (1-((i+1)%2))*c[i] #AC for R6
if (len(temp)%2!=0) and (len(temp)!=0):
AC = ((i+1)%2)*c[i] + (1-((i+1)%2))*p[i] ##ACC for R6
temp.append(AC)
final_A6.append(temp)
final_A6
According to Table 1, the result of A6 is correct as follows.
final_A6 =[[50, 7, 140], [50, 7, 3], [50, 120, 3], [100, 120, 3]]
I used the similar approach for creating the code for Token in Table 1 as follows:
storage_token_A6 = []
for ida in storage_i:
temp_token_A6 = []
for i in ida:
if i == (n-1):
token_A6 = z[i]
if i != (n-1):
if (len(temp_token_A6)==0) or (len(temp_token_A6)%2 ==0):
token_A6 = z[i]
if (len(temp)%2!=0) and (len(temp)!=0):
token_A6 = m[i] - z[i]
temp_token_A6.append(token_A6)
storage_token_A6.append(temp_token_A6)
However the following result is incorrect.
storage_token_A6 = [[0, 1, 3], [0, 1, 0], [0, 3, 0], [1, 3, 0]]
The correct result of token according to the Table 1 is as follows.
expected result = [[0, 1, 1], [0, 1, 1], [0, 3, 1], [2, 3, 1]]
Can anyone let me know what's wrong with the code for Token?
If you have other suggestion or questions, please let me know.
Thank you in advance.

Finding the coordinates of max sum path in matrix

I have this method which returns the max sum of the path from top left to bottom right (can move only to the right or bottom).
def max_path(grid):
N = len(grid)
M = len(grid[0])
sum = [[0 for i in range(M + 1)] for i in range(N + 1)]
for i in range(1, N + 1):
for j in range(1, M + 1):
sum[i][j] = (max(sum[i - 1][j], sum[i][j - 1]) + grid[i - 1][j - 1])
return sum[N][M]
matrix = [[1, 2, 3], [3, 4, 5]]
print(max_path(matrix))
output : 1 + 3 + 4 + 5 = 13
But what I want to get is also the coordinates of the points of the path:
[(0,0) (1,0) (1,1) (1,2)]
You can try the below code to get your job done.
from itertools import permutations, product
def get_max_sum(table):
height, width = len(table), len(table[0])
sum_, *pos = max((sum(table[x][y] for x, y in zip(*pairs)), *zip(*pairs))
for pairs in product(
permutations(range(height)),
([*range(i, width), *range(i)] for i in range(width))))
return (sum_, *sorted(pos))
sum_, *pos = get_max_sum(
[[1, 2, 3],
[2, 3, 5],
[4, 9, 16]]
)
Output:
20 #maximum sum
(0, 1) (1, 0) (2, 2) #co -ordinates
The variable sum after the nested-for loops (as written in your code) is
[0, 0, 0, 0],
[0, 1, 3, 6],
[0, 4, 8, 13]
You can work out the coordinates of the max sum by having a initial "pointer" at the bottom right corner (i=1, j =2, ignoring the zeros), and comparing the values that is on the top (i=0, i=2) and on the left (i=1, j=1). Since 8 is larger than 6, we move the "pointer" to the left, and now i=1, j=1.
4 is larger than 3, so we move the pointer to 4 (i=1, j=0)
1 is larger than 0, so we move the pointer to 1 (i=0, j=0)
A basic (untested) implementation of the algorithm is as follows:
def max_path(grid):
N = len(grid)
M = len(grid[0])
sum = [[0 for i in range(M + 1)] for i in range(N + 1)]
for i in range(1, N + 1):
for j in range(1, M + 1):
sum[i][j] = (max(sum[i - 1][j], sum[i][j - 1]) + grid[i - 1][j - 1])
j = M
i = N
path = []
while i > 0 and j > 0:
path.append((i-1,j-1))
if sum[i-1][j] <= sum[i][j-1]:
j -= 1
else:
i -= 1
path.reverse()
return sum[N][M],path
matrix = [[1, 2, 3], [3, 4, 5]]
print(max_path(matrix))

Min cost path in grid using jumps or unit steps right or down

Assume you have a grid, where each node contains a weight that represents the cost of taking that square.
You start at (0,0) at the top left of the 2D array and you want to get to (X-1, Y-1) where X is the number of columns and Y rows at the bottom right. You can go right 1 square, or you can go down 1 square at a time. You are also given an int array of "jumps", where each value $d_i$ represents the number of squares you can skip over going right or down on the ith jump. The jumps array specifies the order you have to take for jumps, meaning, for instance, you can't take jump[2] of a skip if you haven't used a single one. You can only take len(jump) number of jumps.
We are trying to solve this with dynamic programming. This is what I have thus far:
def helper(grid, jumps):
dCount = 0
dp = [[[0 for k in range(len(jumps)+1)] for j in range(len(grid[0]))] for i in range(len(grid))]
for row in range(len(grid)):
for col in range(len(grid[0])):
if row == 0 and col == 0:
dp[row][col][dCount] += grid[row][col]
jumpRight = float('infinity')
jumpUp = float('infinity')
goUp = float('infinity')
goRight = float('infinity')
if(row > 0):
goUp = dp[row-1][col][dCount]
if(col > 0):
goRight = dp[row][col-1][dCount]
if (dCount < len(jumps)):
jumpRight = dp[row-jumps[dCount]][col][dCount]
jumpUp = dp[row][col-jumps[dCount]][dCount]
res = grid[row][col] + min(goRight, goUp, jumpRight, jumpUp)
if(res == jumpRight or res==jumpUp):
dCount+=1
dp[row][col][dCount] = res
return dp[len(grid)-1][len(grid[0])-1]
grid = [[1, 0, 3, 7, 2, 5], [8, 3, 7, 6, 9, 8], [9, 7, 8, 2, 1, 1], [3, 2, 9, 1, 7, 8]]
jumps = [1, 1]
print(helper(grid,jumps)) #should be 16
However, the code doesn't seem to be working.
The above is just printing out [0 0 15], when I think it should be [0 0 16]
The following is an implementation:
def shortest(grid, jumps, x=0, y=0, jumped=0):
# grid: whole grid
# jumps: jumps to be exhuasted
# x, y: current position
# jumped: number of jumps that have been used
# output: a tuple (cost, path)
# cost: minimum cost from this position to the final position
# path: a list of tuples, each element the position along the minimum-cost path
rows = len(grid) - x; cols = len(grid[0]) - y # remaining num of rows and cols
if (rows, cols) == (1, 1): # if arrived at the southeast corner
return (float('inf'), [(x, y)]) if jumps[jumped:] else (grid[x][y], [(x, y)]) # return inf if jumps are not exhausted
candidates = [] # store results from deeper calls
if rows > 1: # if possible to move down
candidates.append(shortest(grid, jumps, x+1, y, jumped)) # down by one
if jumped < len(jumps) and rows > jumps[jumped] + 1: # if possible to jump
candidates.append(shortest(grid, jumps, x+jumps[jumped]+1, y, jumped+1)) # jump down
if cols > 1: # if possible to move right
candidates.append(shortest(grid, jumps, x, y+1, jumped)) # right by one
if jumped < len(jumps) and cols > jumps[jumped] + 1: # if possible to jump
candidates.append(shortest(grid, jumps, x, y+jumps[jumped]+1, jumped+1)) # jump right
temp = min(candidates, key=lambda x: x[0]) # recall: temp[0]: min_cost, temp[1]: min_path
return (temp[0] + grid[x][y], [(x, y), *temp[1]])
grid = [[1, 0, 3, 7, 2, 5], [8, 3, 7, 6, 9, 8], [9, 7, 8, 2, 1, 1], [3, 2, 9, 1, 7, 8]]
jumps = [1, 1]
print(shortest(grid, jumps)) # (16, [(0, 0), (0, 1), (0, 2), (0, 4), (2, 4), (2, 5), (3, 5)])
The state variables are x, y and jumps; x and y remember where the current position is in the given grid. jumps remembers how many jumps have been used so far.
The end state of the recursion occurs when the position is at the final destination, i.e., [-1, -1]. If the jumps have not been exhausted, then it is a failure; so return the infinity as the cost. Otherwise, return the value at the point as the cost.
Actually, the return is a tuple; the first element is the cost, and the second element is the current position. The second element is used for obtaining the cost-minimization path in the end.
In other states, the recursion is defined in a natural way; the function recurses into (up to) four possible movements: up by one, right by one, jump up, jump right. It compares the resulting costs, and selects the minimum-cost direction.
Note: this uses generalized unpack, introduced in python 3.5. But this is not essential.
Here's an example of a bottom up approach that seems to return correct results for this example and the one in a similar question. I'm not sure the code is foolproof, though.
Python:
def f(grid, jumps):
m, n = len(grid), len(grid[0])
dp = [None] * m
for i in range(m):
dp[i] = [[float('inf')] * (len(jumps) + 1) for j in range(n)]
dp[0][0][0] = grid[0][0]
for y in range(m):
for x in range(n):
for j in range(len(jumps) + 1):
if (y, x, j) == (0, 0, 0):
continue
dp[y][x][j] = grid[y][x] + min(
dp[y - 1][x][j] if y > 0 else float('inf'),
dp[y][x - 1][j] if x > 0 else float('inf'),
dp[y - jumps[j-1] - 1][x][j-1] if (j > 0 and y - jumps[j-1] - 1 >= 0) else float('inf'),
dp[y][x - jumps[j-1] - 1][j-1] if (j > 0 and x - jumps[j-1] - 1 >= 0) else float('inf')
)
return min(dp[m-1][n-1])
grid = [
[1, 0, 3, 7, 2, 5],
[8, 3, 7, 6, 9, 8],
[9, 7, 8, 2, 1, 1],
[3, 2, 9, 1, 7, 8]]
jumps = [1, 1]
print(f(grid, jumps)) # 16
grid = [
[3, 9, 1],
[9, 9, 1],
[9, 9, 1]
]
jumps = [1, 1]
print(f(grid, jumps)) # 5

What cause this weird bug in my selfplaying tetris written in Python 3? [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 2 years ago.
Improve this question
What happen is that at certain point when a piece is put to its place suddenly the a whole column became solid. Putting breakpoint on line 236 one can debug this and see that in the value assignment:
gameSpace[current_y + x][current_x + y] = current_piece + 1
Suddenly not just one field of the gameSpace is changing, but a whole column and its just does not make sense for me. (I'm extremely beginner in Python, written my tetris originally in C on an MCU board and now trying to port to PC to be able find the best parameters for the fitness function.) The indices into the 2D game space are also valid so that could not cause it.
The code:
from tkinter import *
from random import seed
from random import randint
import time
# seed random number generator
seed(1)
# constants
PX_WIDTH = 480
PX_HEIGHT = 640
BLOCK_SIZE = PX_HEIGHT / 20
HEIGHT = int(PX_HEIGHT / BLOCK_SIZE)
WIDTH = int(HEIGHT / 2)
TICK_CNT = 1
current_piece = randint(0, 6)
current_x = 3
current_y = 0
current_rotation = 0
scores = 0
ticks = 0
colors = ["black", "blue", "orange", "green", "yellow", "red", "purple", "brown"]
gameSpaceBOT = [0] * HEIGHT
for i in range(HEIGHT):
gameSpaceBOT[i] = [0] * WIDTH
tetrominos = [
[[0, 1, 0, 0],
[0, 1, 1, 0],
[0, 0, 1, 0],
[0, 0, 0, 0]],
[[0, 1, 0, 0],
[0, 1, 1, 0],
[0, 1, 0, 0],
[0, 0, 0, 0]],
[[0, 0, 1, 0],
[0, 1, 1, 0],
[0, 1, 0, 0],
[0, 0, 0, 0]],
[[0, 1, 0, 0],
[0, 1, 0, 0],
[0, 1, 0, 0],
[0, 1, 0, 0]],
[[0, 1, 1, 0],
[0, 1, 1, 0],
[0, 0, 0, 0],
[0, 0, 0, 0]],
[[0, 1, 0, 0],
[0, 1, 0, 0],
[0, 1, 1, 0],
[0, 0, 0, 0]],
[[0, 0, 1, 0],
[0, 0, 1, 0],
[0, 1, 1, 0],
[0, 0, 0, 0]]
]
def rotatedIndex(rotation, index):
if rotation == 0:
return index
if rotation == 1:
# 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
# 12 8 4 0 13 9 5 1 14 10 6 2 15 11 7 3
return int(12 - ((index % 4) * 4) + int(index / 4))
if rotation == 2:
return 15 - index
if rotation == 3:
# 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
# 3 7 11 15 2 6 10 14 1 5 9 13 0 4 8 12
return int(15 - int(index / 4) - ((3 - (index % 4)) * 4))
def doesItFit(piece, rota, in_x, in_y, gameSpace):
piece_x = in_y
piece_y = in_x
idx = 0
for x in range(4):
for y in range(4):
idx = rotatedIndex(rota, x * 4 + y)
gs_x = piece_x + x
gs_y = piece_y + y
if tetrominos[piece][int(idx / 4)][idx % 4] != 0:
if gs_x >= 0 and gs_x < HEIGHT and gs_y >= 0 and gs_y < WIDTH:
if gameSpace[gs_x][gs_y] != 0:
return 0
else:
return 0
return 1
# print for debug
def printGamespace(gameSpace):
for x in range(HEIGHT):
for y in range(WIDTH):
print(gameSpace[x][y], end=" ")
print()
# drawing the gamespace
def drawGamespace(C, squares_list, gameSpace):
### print("in drawGamespace")
#gameSpace[randint(0, HEIGHT-1)][randint(0, WIDTH-1)] = 1
for y in range(HEIGHT):
for x in range(WIDTH):
C.itemconfig(squares_list[y * WIDTH + x], fill=colors[gameSpace[y][x]])
#draw current piece
for x in range(4):
for y in range(4):
idx = rotatedIndex(current_rotation, x * 4 + y)
if tetrominos[current_piece][int(idx / 4)][idx % 4] != 0:
C.itemconfig(squares_list[(current_y + x) * WIDTH + (current_x + y)], fill="white")
def spawnNewPiece(gameSpace):
### print("in spawnNewPiece")
global current_x
current_x = 3
global current_y
current_y = 0
global current_rotation
current_rotation = randint(0, 3)
global current_piece
current_piece = randint(0, 6)
return doesItFit(current_piece, current_rotation, current_x, current_y, gameSpace)
def calculateFitness(gameSpace):
lineFillednessFactor = 0
lineSolved = 0
for x in range(HEIGHT):
currentRowFilledness = 0
for y in range(WIDTH):
if gameSpace[x][y] != 0:
currentRowFilledness = currentRowFilledness + 1
if currentRowFilledness == WIDTH:
lineSolved += 1
lineFillednessFactor += currentRowFilledness * (x + 1)
return lineFillednessFactor + 10000 * lineSolved
def bot(gameSpace):
global gameSpaceBOT
global current_rotation
global current_x
local_y = current_y
target_x = current_x
target_rot = current_rotation
bestFitness = -1
for x in range(HEIGHT):
for y in range(WIDTH):
gameSpaceBOT[x][y] = gameSpace[x][y]
for rot in range(4):
for x in range(WIDTH + 3):
if doesItFit(current_piece, rot, x - 3 , local_y, gameSpace) == 1:
# moving down until it stucks
while doesItFit(current_piece, rot, x - 3 , local_y + 1, gameSpace) == 1:
local_y = local_y + 1
# fitting the piece into the BOTs gameSpace
for px in range(4):
for py in range(4):
idx = rotatedIndex(rot, px * 4 + py)
if tetrominos[current_piece][int(idx / 4)][idx % 4] == 1:
gameSpaceBOT[local_y + px][x - 3 + py] = current_piece + 1
# if the resulting gamespace fitness is better then the current best one
# then change the target coordinates for the best solution to the current one
if calculateFitness(gameSpaceBOT) > bestFitness:
bestFitness = calculateFitness(gameSpaceBOT)
target_x = x - 3
target_rot = rot
# removing the piece for the next iteration
for px in range(4):
for py in range(4):
idx = rotatedIndex(rot, px * 4 + py)
if tetrominos[current_piece][int(idx / 4)][idx % 4] == 1:
gameSpaceBOT[local_y + px][x - 3 + py] = 0
# depending on our current position move the current piece towards the target
# first do the rotation
### print('target_rot={:d}, target_x={:d}'.format(target_rot, target_x))
if target_rot != current_rotation:
if target_rot > current_rotation:
current_rotation = current_rotation + 1
else:
current_rotation = current_rotation - 1
# if rotation is correct than move it horrizontally
elif target_x != current_x:
if target_x > current_x:
current_x = current_x + 1
else:
current_x = current_x - 1
def checkAndRemoveFilledLines(gameSpace):
global scores
first_found_line_y_coord = 0
found_lines = 0
for x in range(HEIGHT):
num_of_blocks_in_row = 0
for y in range(WIDTH):
if gameSpace[x][y] != 0:
num_of_blocks_in_row = num_of_blocks_in_row + 1
if num_of_blocks_in_row == WIDTH:
found_lines = found_lines + 1
if first_found_line_y_coord == 0:
first_found_line_y_coord = x
# if there was filled lines then add to score and erase the lines
if found_lines != 0:
scores += 10
for x in range(first_found_line_y_coord + found_lines - 1, 0, -1):
### print("x is {:d}".format(x))
gameSpace[x] = gameSpace[x - found_lines]
def update(C, squares_list, gameSpace):
global ticks
ticks = (ticks + 1) % TICK_CNT
global current_y
global scores
bot(gameSpace)
if ticks == 0:
# if it able to move down than move it down
if doesItFit(current_piece, current_rotation, current_x, current_y + 1, gameSpace) == 1:
current_y = current_y + 1
else:
if current_y == 8 and current_piece == 5 and current_x == 5:
print("hey")
scores += 1
for x in range(4):
for y in range(4):
idx = rotatedIndex(current_rotation, x * 4 + y)
if tetrominos[current_piece][int(idx / 4)][idx % 4] != 0:
gameSpace[current_y + x][current_x + y] = current_piece + 1
checkAndRemoveFilledLines(gameSpace)
if not spawnNewPiece(gameSpace):
return 0
drawGamespace(C, squares_list, gameSpace)
C.after(1, update, C, squares_list, gameSpace)
def main():
# canvasd
root = Tk()
C = Canvas(root, bg="black", height=PX_HEIGHT, width=PX_WIDTH)
C.pack()
# for storing the rectangles
squares_list = []
# init
# creating and initializing the game space 2d array
gameSpace = [0] * HEIGHT
for i in range(HEIGHT):
gameSpace[i] = [0] * WIDTH
for y in range(HEIGHT):
for x in range(WIDTH):
squares_list.append(C.create_rectangle(x * BLOCK_SIZE,
y * BLOCK_SIZE,
(x + 1) * BLOCK_SIZE,
(y + 1) * BLOCK_SIZE,
fill=colors[gameSpace[y][x]]))
update(C, squares_list, gameSpace)
root.mainloop()
if __name__ == "__main__":
main()
As it was pointed out by stovfl the problem was indeed that the gameSpace was copied by reference and not by value. Using deepcopy solved it.

Replace all -1 in numpy array with values from another array

I have two numpy arrays, e. g.:
x = np.array([4, -1, 1, -1, -1, 2])
y = np.array([1, 2, 3, 4, 5, 6])
I would like to replace all -1 in x with numbers in y, that are not in x. First -1 with first number in y that is not in x (3), second -1 with second number in y that is not in x (5), ... So final x should be:
[4 3 1 5 6 2]
I created this function:
import numpy as np
import time
start = time.time()
def fill(x, y):
x_i = 0
y_i = 0
while x_i < len(x) and y_i < len(y):
if x[x_i] != -1: # If current value in x is not -1.
x_i += 1
continue
if y[y_i] in x: # If current value in y is already in x.
y_i += 1
continue
x[x_i] = y[y_i] # Replace current -1 in x by current value in y.
for i in range(10000):
x = np.array([4, -1, 1, -1, -1, 2])
y = np.array([1, 2, 3, 4, 5, 6])
fill(x, y)
end = time.time()
print(end - start) # 0.296
It's working, but I need run this function many times (e. g. milion times), so I would like to optimize it. Is there any way?
You could do:
import numpy as np
x = np.array([4, -1, 1, -1, -1, 2])
y = np.array([1, 2, 3, 4, 5, 6])
# create set of choices
sx = set(x)
choices = np.array([yi for yi in y if yi not in sx])
# assign new values
x[x == -1] = choices[:(x == -1).sum()]
print(x)
Output
[4 3 1 5 6 2]
y_not_in_x = np.setdiff1d(y, x)
x_eq_neg1 = x == -1
n_neg1s = np.sum(x_eq_neg1)
x[x_eq_neg1] = y_not_in_x[:n_neg1s]

Categories