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)
So I'm trying to get the positions of pixels that surround a pixel :
for example :
0 0 0 0
x x x 0
x 1 x 0
x x x 0
I need to get the positions of all those Xs.
The problem for me isn't the general case I can do a double-loop to get them, the problem is the conditions. Because what came to my mind is to manually code every case, but it isn't efficient and takes too many lines.
Therefore, I'm asking if there is an easier way to do so
I can program it manually by doing several if statement and assign their values to an array
Here is what i wrote for the moment it takes to many lines and isn't efficient
def cond_i_zero(pos_array,i,j):
pos_array[0] = i
pos_array[1] = j-1
pos_array[2] = i
pos_array[3] = j+1
pos_array[4] = i+1
pos_array[5] = j-1
pos_array[6] = i+1
pos_array[7] = j
pos_array[8] = i+1
pos_array[9] = j+1
return pos_array
def cond_j_zero(pos_array,i,j):
pos_array[0] = i-1
pos_array[1] = j
pos_array[2] = i-1
pos_array[3] = j+1
pos_array[4] = i
pos_array[5] = j+1
pos_array[6] = i+1
pos_array[7] = j
pos_array[8] = i+1
pos_array[9] = j+1
return pos_array
"""
i,j : represent the position of the pixel that is equivalent to 1 in the
example above
total_img_nb : 16 for the example
output expected : array of positions so for example since the maximum of pixels that suround a pixel is 8 the output will be an array of size 16
where every pair number represent the i(row) pos and every odd number represent the j (columns) pos
"""
def pos_in_array(total_imgs_nb,i,j):
x = 2
y = 2
size = int(math.sqrt(total_imgs_nb))-1
if ( i == 0 ):
x = 1
if ( j == 0 ):
y = 1
if ( i == size ):
x = size - 1
if ( j == size ):
y = size - 1
pos_array = np.zeros(( total_imgs_nb ))
pos_array += 999
if((i==0 and j == 0) or (i==size and j == size)):
pos_array[0] = i
pos_array[1] = y
pos_array[2] = x
pos_array[3] = j
pos_array[4] = x
pos_array[5] = y
elif (i==0):
pos_array=cond_i_zero(pos_array,i,j)
elif (j==0):
pos_array=cond_j_zero(pos_array,i,j)
elif (i==size):
pos_array[0] = i
pos_array[1] = y
pos_array[2] = x
pos_array[3] = j
pos_array[4] = x
pos_array[5] = y
pos_array[6] = y
pos_array[7] = y
pos_array[8] = y
pos_array[9] = y
else:
count = 0
for w in range(i-1,i+2):
for v in range(j-1,j+2):
pos_array[count] = w
count = count +1
pos_array[count] = v
count = count +1
return pos_array
def main():
pos_array = pos_in_array(16,1,1)
# this usually return
[0. 0. 0. 1. 0. 2. 1. 0. 1. 2. 2. 0. 2. 1. 2. 2.]
Here is how i did it .
first i get the number of neighbours for the pixel
then i create a 1-D array of double the size of the neighbours and then i bound the loop and add the position to the array .
size = int(math.sqrt(nb_total))
if((i==0 and (j ==0 or j==size-1))or (i==size-1 and (j == size -1 or j==0))):
neighbors = 3
elif(i==0 or j==0 or i==size-1 or j==size-1):
neighbors = 5
else:
neighbors = 8
array_pos = np.zeros((neighbors*2))
count = 0
for x in range(size):
for y in range(size):
if(x == i and y == j ):
continue
if((x < i+2 and y <j+2)and (x> i-2 and y > j-2 )):
array_pos[count] = x
count = count + 1
array_pos[count] = y
count = count + 1
if(count == neighbors*2):
break
if(count == neighbors*2):
break
return array_pos
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) )
For example this is array = [1,2,3,4,3,2,1]
i want computer to choose i=4 and sum both left of the four and right of the four and then compare if they are equal to each other, program prints i value to the screen.
Now i write it in here and it works as long as the i value is 0 but if i want to make this search for i>0 then i gets complicated.
this is my main program:
# importing "array" for array creations
import array as arr
# Function to find sum
# of array exlcuding the
# range which has [a, b]
def sumexcludingrange(li, a, b): # I FOUND THIS FUNCTION ONLINE BUT ALSO DIDN`T WORK EITHER.
sum = 0
add = True
# loop in li
for no in li:
# if no != a then add
if no != a and add == True:
sum = sum + no
# mark when a and b are found
elif no == a:
add = False
elif no == b:
add = True
# print sum
return sum
#lis = [1, 2, 4, 5, 6]
#a = 2
#b = 5
#sumexcludingrange(arr, 0, i-1)
def my(arr):
for i in range(len(arr)):
if i == 0: #this works when array is like [1,0,0,1] and i equals zero
sum_left = arr[0]
sum_right = sum(arr) - arr[0]
while sum_left == sum_right:
print(i)
break
elif i > 0 : # i 1 2 3 4 5 6 7 8 9..
#sumleft and sumright are not right.. what is the issue here?
sum_left = sumexcludingrange(arr, 0, i-1) #result is 16, sumexcludingrange function didn`t
#work.
print (sum_left)
#print(i)
sum_right == sum(arr) - sum_left
#print(sum_right)
#break
while sum_left == sum_right:
print(sum_left)
print(sum_right)
print("they are equal now")
break
else:
print("index cannot be a negative number.")
something = arr.array('i', [1,2,3,4,3,2,1]) # len(arr) = 7
my(something)
After seeing that i need another function to compare two sides of the array, i created a new file and write it in here and somehow it outputs this:
1
13
13
2
10
10
#array[i] array[i+1] .. + array[length-1]
array = [1,2,3,4,5,6,7] # 7 element so length=7,
for i in range(len(array)):
if i > 0 :
ln = len(array) + 1
sum_right = sum(array[i+1:ln])
sum_left = sum(array) - sum_right
print(i)
print(sum_right)
print(sum_right)
the way i think is this:
# array[i] i>0 i={1,2,3,4..}
sum_total = sum(arr) = array[0] + ..+ array[i-1] + array[i] + array[i+1] + ... + array[length-1]
sum_right = array[i+1] + .. + array[length-1]
sum_left = sum_total - sum_right
Is there a better way to accomplish that?
If I understand your question correctly, the solution could be something like this:
array = [1,2,3,4,5,6,7]
a1 = array[:4] # first 4 numbers
a2 = array[-4:] # last 4 numbers
total = sum(array)
diff = total-sum(a2)
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.