I need to find the biggest sequence of zeros next to each other (up down left right).
for example in this example the function should return 6
mat = [[1,**0**,**0**,3,0],
[**0**,**0**,2,3,0],
[2,**0**,**0**,2,0],
[0,1,2,3,3],]
the zeros that i marked as bold should be the answer (6)
the solution should be implemented without any loop (using recursion)
this is what i tried so far
def question_3_b(some_list,index_cord):
y = index_cord[0]
x = index_cord[1]
list_of_nums = []
def main(some_list,index_cord):
y = index_cord[0]
x = index_cord[1]
def check_right(x,y):
if x + 1 < 0:
return 0
if some_list[y][x+1] == 0:
main(some_list,(y,x+1))
else:
return 0
def check_left(x,y):
if x -1 < 0:
return 0
if some_list[y][x - 1] == 0:
main(some_list,(y, x - 1))
def check_down(x,y):
if y + 1 < 0:
return 0
try:
if some_list[y + 1][x] == 0:
main(some_list,(y + 1, x))
except:
print("out of range")
def check_up(x,y):
counter_up = 0
if y - 1 < 0:
return 0
if some_list[y - 1][x] == 0:
counter_up += 1
main(some_list,(y - 1, x))
list_of_nums.append((x,y))
right = check_right(x,y)
down = check_down(x,y)
left = check_left(x,y)
up = check_up(x, y)
main(some_list,index_cord)
print(list_of_nums)
question_3_b(mat,(0,1))
Solution #1: classic BFS
As I mention in a comment, you can tackle this problem using BFS (Breadth First Search), it will be something like this:
# This function will give the valid adjacent positions
# of a given position according the matrix size (NxM)
def valid_adj(i, j, N, M):
adjs = [[i + 1, j], [i - 1, j], [i, j + 1], [i, j - 1]]
for a_i, a_j in adjs:
if 0 <= a_i < N and 0 <= a_j < M:
yield a_i, a_j
def biggest_zero_chunk(mat):
answer = 0
N, M = len(mat), len(mat[0])
# Mark all non zero position as visited (we are not instrested in them)
mask = [[mat[i][j] != 0 for j in range(M)] for i in range(N)]
queue = []
for i in range(N):
for j in range(M):
if mask[i][j]: # You have visited this position
continue
# Here comes the BFS
# It visits all the adjacent zeros recursively,
# count them and mark them as visited
current_ans = 1
queue = [[i,j]]
while queue:
pos_i, pos_j = queue.pop(0)
mask[pos_i][pos_j] = True
for a_i, a_j in valid_adj(pos_i, pos_j, N, M):
if mat[a_i][a_j] == 0 and not mask[a_i][a_j]:
queue.append([a_i, a_j])
current_ans += 1
answer = max(answer, current_ans)
return answer
mat = [[1,0,0,3,0],
[0,0,2,3,0],
[2,0,0,2,0],
[0,1,2,3,3],]
mat2 = [[1,0,0,3,0],
[0,0,2,3,0],
[2,0,0,0,0], # A slight modification in this row to connect two chunks
[0,1,2,3,3],]
print(biggest_zero_chunk(mat))
print(biggest_zero_chunk(mat2))
Output:
6
10
Solution #2: using only recursion (no for statements)
def count_zeros(mat, i, j, N, M):
# Base case
# Don't search zero chunks if invalid position or non zero values
if i < 0 or i >= N or j < 0 or j >= M or mat[i][j] != 0:
return 0
ans = 1 # To count the current zero we start at 1
mat[i][j] = 1 # To erase the current zero and don't count it again
ans += count_zeros(mat, i - 1, j, N, M) # Up
ans += count_zeros(mat, i + 1, j, N, M) # Down
ans += count_zeros(mat, i, j - 1, N, M) # Left
ans += count_zeros(mat, i, j + 1, N, M) # Right
return ans
def biggest_zero_chunk(mat, i = 0, j = 0, current_ans = 0):
N, M = len(mat), len(mat[0])
# Base case (last position of mat)
if i == N - 1 and j == M - 1:
return current_ans
next_j = (j + 1) % M # Move to next column, 0 if j is the last one
next_i = i + 1 if next_j == 0 else i # Move to next row if j is 0
ans = count_zeros(mat, i, j, N, M) # Count zeros from this position
current_ans = max(ans, current_ans) # Update the current answer
return biggest_zero_chunk(mat, next_i, next_j, current_ans) # Check the rest of mat
mat = [[1,0,0,3,0],
[0,0,2,3,0],
[2,0,0,2,0],
[0,1,2,3,3],]
mat2 = [[1,0,0,3,0],
[0,0,2,3,0],
[2,0,0,0,0], # A slight modification in this row to connect two chunks
[0,1,2,3,3],]
print(biggest_zero_chunk(mat.copy()))
print(biggest_zero_chunk(mat2.copy()))
Output:
6
10
Notes:
The idea behind this solution is still BFS (represented mainly in the count_zeros function). Also, if you are interested in using the matrix values after this you should call the biggest_zero_chunk with a copy of the matrix (because it is modified in the algorithm)
i'm trying to find the start and stop of a matrix inside a matrix
For example theres a matrix of W and B, B is a square inside the whole matrix:
5 6
WWBBBW
WWBBBW
WWBBBW
WWWWWW
WWWWWW
i want to get the middle of:
BBB
BBB
BBB
which should output me:
2 4
because the matrix is in another matrix
My idea was to take the square and make the middle B1
then index it inside of the whole matrix.
I've tried the code as following which i made.
def middle(m):
# for getting the middle of BlackPart
n = len(m)//2
n1 = len(m[n])//2
m[n][n1] = "B1"
return m
def find(matrix, list1):
# for getting B list
for i in range(len(matrix)):
for j in range(len(matrix[i])):
if matrix[i][j] == "B":
list1.append("B")
return list1
def q2():
# for getting matrix
nope = input("").split(" ")
counter1 = 0
m = []
while counter1 < int(nope[0]):
a = input("")
m.append(list(a))
counter1 += 1
# for getting matrix
# below is for getting a square matrix
l = []
find(m, l)
n = int(len(l) ** (1 / 2))
counter = 0
for i in range(len(l) // 3):
l += [l[counter * n: counter * n + n]]
counter += 1
middle(m)
q2()
But it was too complicated and confused me, then i ended up noting it as a failure.
Please tell me if there is an easier way to do this.
Thanks
There you go, I figured it out:
matrix = """WWBBBW
WWBBBW
WWBBBW
WWWWWW
WWWWWW"""
bstart = 0
bend = 0
bfound = False
bposition_x = 0
bposition_y = 0
bstartline = 0
bfoundinlines = []
matrix = matrix.split("\n")
for linenum, line in enumerate(matrix):
bfound = False
for index, x in enumerate(line):
if x == "B" and bfound == False:
bstart = index
bfound = True
bfoundinlines.append(linenum)
elif x == "W" and bfound == True:
bend = index - 1
bstartline += 1
bposition_x = int((bstart + bend)/2 + 1)
bposition_y = int(round(len(bfoundinlines)/2)) # 1 already added (counting from 1)
if len(bfoundinlines) == 1: bposition_y = 2 #python rounds 0.5 to 0
print("from top:",bposition_y,"from left",bposition_x)
Can someone help me replace the for loop to while loop I'm struggling to figure it out?
The question specifically asks us not to use for loop. That's why I need to replace it with the while loop
I have listed below:
my code
Sample testing of the input and the output
the conditions we have to follow:
def matrix_equal(matrix1, matrix2):
"""
-------------------------------------------------------
Compares two matrices to see if they are equal - i.e. have the
same contents in the same locations.
Use: equal = matrix_equal(matrix1, matrix2)
-------------------------------------------------------
Parameters:
matrix1 - the first matrix (2D list of ?)
matrix2 - the second matrix (2D list of ?)
Returns:
equal - True if matrix1 and matrix2 are equal,
False otherwise (boolean)
------------------------------------------------------
"""
equal = True
if((len(matrix1) != len(matrix2)) or (len(matrix1[0]) != len(matrix2[0]))):
equal = False
for x in range(len(matrix1)):
if(equal == False):
break
for y in range(len(matrix1[0])):
num1 = matrix1[x][y]
num2 = matrix2[x][y]
if(num1 != num2):
equal = False
break
return equal
Sample testing:
First matrix:
0 1 2
0 c a t
1 d o g
2 b i g
Second matrix:
0 1 2
0 c a t
1 d o g
2 b i g
Equal matrices: True
The conditions we have to follow:
1. should not call input in the function
2. should not call print in the function
3. should not have multiple returns
This should solve your problem, this is a solution using while loop :
def matrix_equal(mat1,mat2):
equal = True
if(len(mat1[0]) == len(mat2[0]) and len(mat1) == len(mat2)):
i = 0
n = len(mat1[0])
m = len(mat1)
while(i < m):
j = 0
while(j < n):
if(mat1[i][j] != mat2[i][j]):
equal = False
break
j+=1
if(equal==False):
break
i+=1
else:
equal = False
return equal
Change
for x in range(len(matrix1)):
to
x = 0
while x < len(matrix1):
x += 1
Cheers!
You can transform :
for i in range(mat.shape[0]):
{do stuff...}
into
i = 0
while i < mat.shape[0]:
{do stuff...}
# increment i with 1
i += 1
so here you would get :
def mat_eq_while(matrix1, matrix2):
i = 0
j = 0
equal = True
if(not (mat1.shape == mat2.shape) ):
equal = False
while i < mat1.shape[0]:
if(equal == False):
break
while j < mat1.shape[1]:
num1 = matrix1[i, j]
num2 = matrix2[i, j]
if(num1 != num2):
equal = False
break
j += 1
i += 1
return equal
test it with
import numpy as np
mat1 = np.matrix(range(9)).reshape(3,3)
mat2 = np.matrix(range(1, 10)).reshape(3,3)
print( mat_eq_while(mat1, mat1) )
print( mat_eq_while(mat1, mat2) )
I have the following algo:
Iterate through all rows in 2d-array:
For each processed row I get 1d-array
Replace row i of other 2d-array with processed 1-d array
I'd like to parallelize the process as each row process is independant.
My code:
def update_grid_row(self, grid, new_neighbours_grid, y):
grid_row = np.zeros(GRID_WIDTH + 2)
for x in range(0, GRID_WIDTH):
xy_status = self.get_status_grid(x, y, grid, new_neighbours_grid)
grid_row[x + 1] = xy_status
return grid_row
def get_status_grid(self, x, y, new_grid, new_neighbours_grid):
current_status = new_grid[x + 1][y + 1]
living_neighbours = new_neighbours_grid[x][y]
if living_neighbours < 2 or living_neighbours > 3:
return int(0)
elif current_status == 0 and living_neighbours == 3:
return int(1)
else:
return current_status
def run
original_grid = self.grid
new_grid = original_grid
new_neighbours_grid = self.get_neighbours_grid(new_grid)
for y in range(0, GRID_HEIGHT):
grid_row = self.update_grid_row(original_grid, new_neighbours_grid, y)
new_grid[:, y + 1] = grid_row.T
self.grid = new_grid
Multiprocessing is probably not useful, as pointed out in the comments, but notice that what your neighbor counting corresponds to convolving your grid with the array
1 1 1
1 0 1
1 1 1
So, using scipy.signal.convolve2d will buy you a factor of somewhere 10 and 100.
Below is the code I have written. It says the list assingment index is out of range. I can't seem to figure out where I've gone wrong here. Maybe someone could elaborate as to where the error is.
def genarator(x, y):
square = x * y
matrix = [[]]
matrix2 = []
i = 0
while square > 0:
j = 0
while x > j:
matrix[i][j] = int(raw_input("Enter the matrix number"))
j = 1
i = 1
square = -square
matrix2 = matrix2 + matrix
return matrix2
def main():
matrix3 = []
x = int(raw_input("Enter the width of your matrix"))
y = int(raw_input("Enter the Length of your matrix"))
matrix3 = genarator(x, y)
print(matrix3)
return 0
main()
###EDIT###########I SOLVED THE PROBLEM
def generator(x, y):
matrix = [[0 for i in range(x)] for j in range(y)]
turns = x
i = 0
j = 0
while turns > 0:
while i < x:
while j < y:
matrix[i][j] = int(raw_input("Enter Array values"))
j += 1
j = 0
i += 1
turns -= 1
print(matrix)
def main():
x = int(raw_input("Enter array length"))
y = int(raw_input("Enter array width"))
print(generator(x, y))
return 0
main()
If you try the following snippet:
x = []
x[0] = 4
You will see that there is an error. The reason for this is that x[0] has not yet been defined, so it can not be modified. To fix your error, you will have to append something to your list before modifying it:
def genarator(x, y):
square = x * y
matrix = [[]]
matrix2 = []
i = 0
while square > 0:
matrix.append([])
j = 0
while x > j:
matrix[-1].append(int(raw_input("Enter the matrix number")))
j = 1
i = 1
square = -square
matrix2 = matrix2 + matrix
return matrix2
I also modified the indexing because -1 will give you the last item, which is what you want.