I need to find the longest path of 0's in a 2d matrix recursively and can't figure out how to do it.( from a given (i , j) it can only move up, down, right or left)
For example this matrix:
mat = [[1, 0, 0, 3, 0],
[0, 0, 2, 3, 0],
[2, 0, 0, 2, 0],
[0, 1, 2, 3, 3]]
print(question3_b(mat))
This should return 6 as there are communities of sizes 1,3,6.
My attempt: I created a few wrapper functions to find the maximum in a list, and a function to find the route at a given (i,j) element and add it to a list, and doing this on every point(i,j) in the matrix.
def question3_b(mat) -> int:
rows: int = len(mat)
cols: int = len(mat[0])
community_lengths = list()
for i in range(rows):
for j in range(cols):
visited = zeros(rows, cols) # create a 2d list of 0's with size rows,cols
a = findcommunity(mat, (i, j), visited)
print("a=", a)
community_lengths.append(a)
print(community_lengths)
return findmax(community_lengths)
def findcommunity(mat: list, indices: tuple, visited: list): # find length of community
#global rec_counter
#rec_counter += 1
i, j = indices
rows = len(mat)
cols = len(mat[0])
if mat[i][j] == 0:
visited[i][j] = 1
if i < rows - 1:
if visited[i + 1][j] == 0:
return 1 + findcommunity(mat, (i + 1, j), visited)
if j < cols - 1:
if visited[i][j + 1] == 0:
return 1 + findcommunity(mat, (i, j + 1), visited)
if i > 0:
if visited[i - 1][j] == 0:
return 1 + findcommunity(mat, (i - 1, j), visited)
if j > 0:
if visited[i][j - 1] == 0:
return 1 + findcommunity(mat, (i, j - 1), visited)
else: # mat[i][j]!=0
return 0
def zeros(rows:int,cols:int)->list: #create a 2d matrix of zeros with size (rows,cols)
if rows==1 and cols==1:return [[0]]
if rows==1 and cols>1:return [[0]*cols]
if rows>1 and cols>1:return zeros(rows-1,cols)+zeros(1,cols)
def findmax(arr:list)->int: # find max in an array using recursion
if len(arr)==2:
if arr[0]>arr[1]:return arr[0]
else:return arr[1]
else:
if arr[0]>arr[1]:
arr[1]=arr[0]
return findmax(arr[1:])
else:
return findmax(arr[1:])
Where did I go wrong? for a matrix of 4X4 zeros, I expect it to run 16*16 times[16 times for each i,j, and there are 16 elements in the matrix]. but it only runs once.
zeros is a recursive function I made that functions like np.zeros, it creates a 2d matrix full of 0's with specified size.
It got really messy but I tried to just change your code instead of writing a new solution. You should have a look at collections deque. Saw this several times where people keep track of visited a lot easier.
I changed visited to outside of the loop and defined it with np.zeros (didn't have your function ;) ). I'm not sure if your recursive function calls at return were wrong but your if-statements were, or at least the logic behind it (or I didn't understand, also possible :) )
I changed that block completly. The first time you come across a 0 in mat the recursive part will dig into the mat as long as it finds another 0 left,right,bottom or top of it (that's the functionality behind dc and dr). That's where the community_counter is increasing. If the function is returning the last time and you jump out to the outerloop in question_3b the counter gets resetted and searchs for the next 0 (next start of another community).
import numpy as np
def question3_b(mat) -> int:
rows: int = len(mat)
cols: int = len(mat[0])
community_lengths = list()
visited = np.zeros((rows, cols)) # create a 2d list of 0's with size rows,cols
community_count = 0
for row in range(rows):
for col in range(cols):
if visited[row][col]==0:
community_count,visited = findcommunity(mat, (row, col), visited, community_count)
if community_count!=0:
community_lengths.append(community_count)
community_count=0
return community_lengths
def findcommunity(mat: list, indices: tuple, visited: list,community_count: int): # find length of community
i, j = indices
rows = len(mat)
cols = len(mat[0])
visited[i][j] = 1
if mat[i][j] == 0:
community_count += 1
dr = [-1, 0, 1, 0]
dc = [0,-1, 0, 1]
for k in range(4):
rr = i + dr[k]
cc = j + dc[k]
if 0<=rr<rows and 0<=cc<cols:
if visited[rr][cc]==0 and mat[rr][cc]==0:
community_count, visited = findcommunity(mat, (rr,cc), visited, community_count)
return community_count,visited
else:
return community_count,visited
mat = [[1, 0, 0, 3, 0],
[0, 0, 2, 3, 0],
[2, 0, 0, 2, 0],
[0, 1, 2, 3, 3]]
all_communities = question3_b(mat)
print(all_communities)
# [6, 3, 1]
print(max(all_communities))
# 6
EDIT
Here is the findcommunity function in your way. Tested it and it works aswell.
def findcommunity(mat: list, indices: tuple, visited: list,community_count: int): # find length of community
i, j = indices
rows = len(mat)
cols = len(mat[0])
visited[i][j] = 1
if mat[i][j] == 0:
community_count += 1
if i < rows - 1:
if visited[i + 1][j] == 0:
community_count, visited = findcommunity(mat, (i + 1, j), visited, community_count)
if j < cols - 1:
if visited[i][j + 1] == 0:
community_count, visited = findcommunity(mat, (i, j + 1), visited, community_count)
if i > 0:
if visited[i - 1][j] == 0:
community_count, visited = findcommunity(mat, (i - 1, j), visited, community_count)
if j > 0:
if visited[i][j - 1] == 0:
community_count, visited = findcommunity(mat, (i, j - 1), visited, community_count)
return community_count,visited
else:
return community_count,visited
Here a completely different approach, in case someone is interested.
import numpy as np
mat = [[1, 0, 0, 3, 0],
[0, 0, 2, 3, 0],
[2, 0, 0, 2, 0],
[0, 1, 2, 3, 3]]
mat = np.array(mat)
# some padding of -1 to prevent index error
mask = np.full(np.array(mat.shape) + 2, -1)
mask[1:-1, 1:-1 ] = mat
# visiteds are set to -2
def trace(f, pt):
mask[tuple(pt)], pts = -2, [pt - 1]
pts += [trace(f, pt + d) for d in
([0, 1], [1, 0], [0, -1], [-1, 0]) if
mask[tuple(pt + d)] == f]
return pts
clusters = lambda f: {tuple(pt-1): trace(f, pt) for pt in np.argwhere(mask==f) if mask[tuple(pt)]==f}
# now call with value your looking for
print(clusters(0))
Related
I have a simple exam to pass where I have to write a program where I create a binary matrix and a pattern and I have to find the pattern inside the matrix and to highlight it if found. I can't use any external library - specially numpy.
What I have atm are just some highlighted numbers that don't match my pattern. I don't know how to continue. Can someone help me please?
My code is this:
pattern.py:
# to create a matrix from an array of arrays
def create(n, m, data):
matrix = []
for i in range(n): #n=rows number
row = []
for j in range(m): #m=columns number
if data[j] not in matrix:
row.append(data[m * i + j])
matrix.append(row)
return matrix
# to colour the elements in 1 inside the pattern
def colora(element):
if element == 1:
element = '\u001b[36m1'
elif element == 0:
element = '\u001b[00m0'
return element
# my pattern forms an I vertically - I should also find it if horizontal
def patternI():
array = [1, 0, 0, 1, 0, 0, 1, 0, 0]
pattern = create(3, 3, array)
for i in range(3):
for j in range(3):
col_element = colora(pattern[i][j])
print(col_element, end=" ")
# print(pattern[i][j], end=" ")
print()
return pattern
main.py:
import patterns
import ricerca
# to create and print the matrix
def matrix():
m = 5
n = 5
array = [0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1, 1, 0]
matrix = patterns.create(n, m, array)
for i in range(n):
for j in range(m):
print(matrix[i][j], end=" ")
print()
return matrix
def main():
print("pattern:")
pattern = patterns.patternI()
print("\r")
print("matrix:")
matrice = matrix()
print("\r")
print("risult:")
newArray=ricerca.ricerca(pattern, matrice)
main()
ricerca.py:
import patterns
# to search the pattern (m_piccola) inside the (m_grande)
def ricerca(m_piccola, m_grande) :
daricordare = [] #an array to fill with the position of the matrix which combines a little with the pattern
for jR in range(len(m_piccola) - 1) :
for iR in range(len(m_grande)) :
for iC in range(len(m_grande[0])) :
for jC in range(len(m_piccola[jR])) :
if m_piccola[jR][jC] == 0 :
jC += 1
break
if m_piccola[jR][jC] == 1 :
if m_grande[iR][iC] == m_piccola[jR][jC] :
daricordare.append((iR, iC))
else :
iC += 1
data = coloraQuelliDelPattern(daricordare, m_grande)
for i in range(5):
for j in range(5):
print(data[i][j], end = " ")
print()
return data
# to highlight the numbers in the array which are inside "daricordare"
def coloraQuelliDelPattern(daricordare, array) :
for i in range(len(daricordare) - 2) :
a = daricordare[i]
b = daricordare[i + 1]
c = daricordare[i + 2]
if b[1] == a[1] + 1 and c[1]==a[1] + 2:
array[a[0]][a[1]] = "\u001b[36m1"
array[b[0]][b[1]] = "\u001b[36m1"
array[c[0]][c[1]] = "\u001b[36m1"
if b[1] != a[1] + 1 or c[1] != a[1] + 2 :
array[a[0]][a[1]] = "\u001b[00m1"
array[b[0]][b[1]] = "\u001b[00m1"
array[c[0]][c[1]] = "\u001b[00m1"
return array
I'm trying to find the solution for Leetcode question #1254, finding the number of closed islands.
Given a 2D grid consists of 0s (land) and 1s (water). An island is a maximal 4-directionally connected group of 0s and a closed island is an island totally (all left, top, right, bottom) surrounded by 1s.
The way I want to solve this problem is by using a boolean value that decides whether an island has any corner values.
I understand that passing a boolean value as an argument to a function that manipulates its value does not work since it is a local variable.
However, for some reason, the code that I found from geeksforgeeks uses the same method, but it works while mine keeps giving a wrong result.
The following is my code and the one at the bottom is from geeksforgeeks.
class Solution:
def closedIsland(self, grid: List[List[int]]) -> int:
numOfRow, numOfCol = len(grid), len(grid[0])
if numOfRow == 0 or grid == None: return 0
counter = 0
def dfs(row, col, hasCorner):
if not(0 <= row < numOfRow and 0 <= col < numOfCol):
return
if grid[row][col] == 2 or grid[row][col] == 1:
return
else:
if (row == 0 or row == numOfRow -1 or col == 0 or col == numOfCol - 1):
hasCorner = True
grid[row][col] = 2
if numOfRow > row >= 0 and numOfCol > col >= 0 and grid[row][col]:
dfs(row - 1, col, hasCorner)
dfs(row + 1, col, hasCorner)
dfs(row, col - 1, hasCorner)
dfs(row, col + 1, hasCorner)
for row in range(len(grid)):
for col in range(len(grid[0])):
if grid[row][col] == 0:
hasCorner = False
dfs(row, col, hasCorner)
if (hasCorner == False):
counter += 1
print(grid)
return counter
# Python3 program for the above approach
# DFS Traversal to find the count of
# island surrounded by water
def dfs(matrix, visited, x, y, n, m, hasCornerCell):
# If the land is already visited
# or there is no land or the
# coordinates gone out of matrix
# break function as there
# will be no islands
if (x < 0 or y < 0 or
x >= n or y >= m or
visited[x][y] == True or
matrix[x][y] == 0):
return
if (x == 0 or y == 0 or
x == n - 1 or y == m - 1):
if (matrix[x][y] == 1):
hasCornerCell = True
# Mark land as visited
visited[x][y] = True
# Traverse to all adjacent elements
dfs(matrix, visited, x + 1, y, n, m, hasCornerCell)
dfs(matrix, visited, x, y + 1, n, m, hasCornerCell)
dfs(matrix, visited, x - 1, y, n, m, hasCornerCell)
dfs(matrix, visited, x, y - 1, n, m, hasCornerCell)
# Function that counts the closed island
def countClosedIsland(matrix, n, m):
# Create boolean 2D visited matrix
# to keep track of visited cell
# Initially all elements are
# unvisited.
visited = [[False for i in range(m)]
for j in range(n)]
result = 0
# Mark visited all lands
# that are reachable from edge
for i in range(n):
for j in range(m):
if ((i != 0 and j != 0 and
i != n - 1 and j != m - 1) and
matrix[i][j] == 1 and
visited[i][j] == False):
# Determine if the island is closed
hasCornerCell = False
# hasCornerCell will be updated to
# true while DFS traversal if there
# is a cell with value '1' on the corner
dfs(matrix, visited, i, j,
n, m, hasCornerCell)
# If the island is closed
if (not hasCornerCell):
result = result + 1
# Return the final count
return result
# Driver Code
# Given size of Matrix
N, M = 5, 8
# Given Matrix
matrix = [ [ 0, 0, 0, 0, 0, 0, 0, 1 ],
[ 0, 1, 1, 1, 1, 0, 0, 1 ],
[ 0, 1, 0, 1, 0, 0, 0, 1 ],
[ 0, 1, 1, 1, 1, 0, 1, 0 ],
[ 0, 0, 0, 0, 0, 0, 0, 1 ] ]
# Function Call
print(countClosedIsland(matrix, N, M))
# This code is contributed by divyeshrabadiya07
Please help me find what I'm missing here
I'm trying to make a IDDFS algorithm for a n-puzzle problem. However, the move function doesn't work properly. It will output the next move but change the values of the previous one (argument). Any advice on how to prevent this from happening would be greatly appreciated :)
def move_blank(i, j, n):
if i + 1 < n:
yield i + 1, j
elif i - 1 >= 0:
yield i - 1, j
elif j + 1 < n:
yield i, j + 1
elif j - 1 >= 0:
yield i, j - 1
def move(state):
[i, j, grid] = state
n = len(grid)
for pos in move_blank(i, j, n):
i1, j1 = pos
grid[i][j], grid[i1][j1] = grid[i1][j1], grid[i][j]
yield [i1, j1, grid]
grid[i][j], grid[i1][j1] = grid[i1][j1], grid[i][j]
def is_goal(state, goal):
return state == goal
def dfs_rec(puz, goal):
if is_goal(puz[-1], goal):
return puz
else:
for next_state in move(puz[-1]):
if next_state not in puz:
next_path = puz + [next_state]
solution = dfs_rec(next_path, goal)
if solution != None:
return solution
return None
goal = [0, 2, [[3, 2, 0], [6, 1, 8], [4, 7, 5]]]
test = [0, 0, [[0, 7, 1], [4, 3, 2], [8, 6, 5]]]
path = dfs_rec([test], goal)
The problem is in move_blank. The generated moves are not mutually exclusive, yet only one of them will be generated. Replace all elifs with a simple if:
def move_blank(i, j, n):
if i + 1 < n:
yield i + 1, j
if i - 1 >= 0:
yield i - 1, j
if j + 1 < n:
yield i, j + 1
if j - 1 >= 0:
yield i, j - 1
There are other, less critical, issues with implementation:
if next_state not in puz is awfully expensive. Enumerating states and storing their id in a set would be much better (there are 362k states for an 8-puzzle, list lookup is faster than set only up to ~30 elements)
reliance on mutable arguments isn't a good practice. No immediate issues here but it might bite when you don't expect.
Storing state as a 9-tuple would fix this and the previous concern.
solution = dfs_rec(next_path, goal) This problem is solvable and would be much cheaper without recursion. Yes, wikipedia pseudocode is not optimal.
it is not IDDFS - there is no depth limit per iteration
there is an issue that i am trying to solve which requires me to generate the indices for an n - dimensional list. Eg: [5, 4, 3] is a 3 dimensional list so valid indices are [0, 0, 0], [0, 0, 1], [0, 1, 0] ... [2, 2, 1] ..... [4, 3, 2]. The best I could come up with a recursive algorithm but this isn't constant space
def f1(dims):
def recur(res, lst, depth, dims):
if depth == len(dims):
res.append(lst[::])
return
curr = dims[depth]
for i in range(curr):
lst[depth] = i
recur(res, lst, depth + 1, dims)
res = []
lst = [0] * len(dims)
recur(res, lst, 0, dims)
return res
the dimensions can be any number , ie: 4D, 5D, 15D etc. Each time it would be given in the form of a list . Eg: 5D would be [3,2,1,5,2] and I would need to generate all the valid indices for these while using constant space ( just while loops and indices processing ) . How would I go about generating these efficiently without the help of any in built python functions ( just while, for loops etc )
This is a working solution in constant space (a single loop variable i, and a vector idx of which modified copies are being yielded, and a single temporary length variable n to avoid calling len() on every iteration):
def all_indices(dimensions):
n = len(dimensions)
idx = [0] * n
while True:
for i in range(n):
yield tuple(idx)
if idx[i] + 1 < dimensions[i]:
idx[i] += 1
break
else:
idx[i] = 0
if not any(idx):
break
print(list(all_indices([3, 2, 1])))
Result:
[(0, 0, 0), (1, 0, 0), (2, 0, 0), (0, 0, 0), (0, 1, 0), (1, 1, 0), (2, 1, 0), (0, 1, 0), (0, 0, 0)]
As pointed out in the comments, there's duplicates there, a bit sloppy, this is cleaner:
def all_indices(dimensions):
n = len(dimensions)
idx = [0] * n
yield tuple(idx) # yield the initial 'all zeroes' state
while True:
for i in range(n):
if idx[i] + 1 < dimensions[i]:
idx[i] += 1
yield tuple(idx) # yield new states
break
else:
idx[i] = 0 # no yield, repeated state
if not any(idx):
break
print(list(all_indices([3, 2, 1])))
Alternatively, you could yield before the break instead of at the start of the loop, but I feel having the 'all zeroes' at the start looks cleaner.
The break is there to force a depth first on running through the indices, which ensures the loop never reaches 'all zeroes' again before having passed all possibilities. Try removing the break and then passing in something like [2, 1, 2] and you'll find it is missing a result.
I think a break is actually the 'clean' way to do it, since it allows using a simple for instead of using a while with a more complicated condition and a separate increment statement. You could do that though:
def all_indices3(dimensions):
n = len(dimensions)
idx = [1] + [0] * (n - 1)
yield tuple([0] * n)
while any(idx):
yield tuple(idx)
i = 0
while i < n and idx[i] + 1 == dimensions[i]:
idx[i] = 0
i += 1 % n
if i < n:
idx[i] += 1
This has the same result, but only uses while, if and yields the results in the same order.
I am currently creating minesweeper, and have got to the part where i have to create a function that once the player clicks on a cell that is empty, it reveals that cell and all other empty cells including the numbered cells that surround the cluster of empty cells ( come on guys, you know minesweeper :) my approach to programming this game, is to have a list of lists which contain values, 0 is empty, 1-8 is how many bombs are touching that cell, and 50 is a bomb. i call this grid. I then use this grid to map out the whole game. That grid is then hidden with a use of another list of lists, which all contain booleans. True is hidden, False is revealed. I call this boolgrid. for example when a player clicks on cell[2][10] the boolgrid[2][10] turns False, revealing that cell.
When an empty cell is selected, the surrounding cells have to be revealed, which in some cases, are also empty, so the surrounding cells of THAT cell need to be revealed, and so on. My problem is writing a function that supports that, i have tried many things, like creating a list of tuples of cell coordinates where the cell == 0, and then a new list to hold all of the new tuples which can eventually be used to turn all of the corresponding boolgrid cells to False. it doesnt work very well, is messy, unpythonic, takes up alot of memory.
I would be most grateful to anyone who can help me with a function that gives me some pythonic way of achieving this.
below is some stripped down code, which contains the bare elements. the code contains all 0's in the grid so every bool should turn False
# used to hold values to denote what the cell contains,
grid = [[0 for x in range(30)] for x in range(15)]
# used to check what cell is hidden, true is hidden, false is revealed,
booleangrid = [[True for x in range(30)] for x in range(15)]
list_to_hold_tuples = []
def find_connected_0_value_cells(cell):
i = 5 # used as an example in the real program these are whatever cell the player selects
j = 10 # as above
# this function should be given an argument of a cell that the player selected.
# reveal the surrounding cells, AND THEN take each surrounding cell, and go through
# the same process again, until every surrounding cell containing 0, and its surrounding
# cells containing zero have been revealed.
# i know i need some kind of loop, but cannot seem to build it.
# currently this function just reveals the cell and its immediate surrounding cells
if cell[i][j] == 0:
s = i, j + 1
t = i, j - 1
u = i - 1, j - 1
v = i - 1, j
w = i - 1, j + 1
x = i + 1, j - 1
y = i + 1, j
z = i + 1, j + 1
tempholding = [s, t, u, v, w, x, y, z]
for i in tempholding:
list_to_hold_tuples.append(i)
def reveal_empty_cells():
for a,b in list_to_hold_tuples:
booleangrid[a][b] = False
print(booleangrid)
find_connected_0_value_cells(grid)
reveal_empty_cells()
I have refactored and got the rest of it to work.
thanks #zettatekdev
grid = [[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[1, 1, 2, 1, 0, 0, 0, 0, 0, 0],
[1, 1, 2, 2, 0, 0, 0, 0, 0, 0],
[1, 1, 2, 3, 0, 0, 0, 0, 0, 0],
[1, 1, 2, 5, 0, 0, 0, 0, 0, 0],
[1, 1, 2, 5, 0, 0, 0, 0, 0, 0]]
list_to_hold_tuples = []
list_change_boolgrid =[]
row = 6
cell = 10
booleangrid = [[True for x in range(cell)] for x in range(row)]
def find_connected_0_value_cells(a, b):
list_to_hold_tuples.append((a, b))
if grid[a][b] == 0:
coord_list = get_surrounding_coords(a, b)
for a,b in coord_list:
if check_coord_values(a, b):
if grid[a][b] != 0:
c = a,b
if c not in list_to_hold_tuples:
list_to_hold_tuples.append(c)
else:
c = a,b
if c not in list_to_hold_tuples:
find_connected_0_value_cells(a,b)
def add_surrounding_cells():
extra_coord = True
for a,b in list_to_hold_tuples:
if grid[a][b] == 0:
coord_list = get_surrounding_coords(a,b, extra_coord)
for i in coord_list:
if i not in list_change_boolgrid:
list_change_boolgrid.append(i)
else:
c = a,b
if c not in list_change_boolgrid:
list_change_boolgrid.append(c)
def reveal_empty_cells():
global booleangrid
for a, b in list_change_boolgrid:
if check_coord_values(a,b):
booleangrid[a][b] = False
def check_coord_values(a,b):
if a == -1 or a >= row:
return False
if b == -1 or b >= cell:
return False
else:
return True
def get_surrounding_coords(a, b, *extra_coord):
c = (a, b + 1)
d = (a, b - 1)
e = (a - 1, b - 1)
f = (a - 1, b)
g = (a - 1, b + 1)
h = (a + 1, b - 1)
i = (a + 1, b)
j = (a + 1, b + 1)
if extra_coord:
k = (a, b)
return [c, d, e, f, g, h, i, j, k]
return [c, d, e, f, g, h, i, j]
find_connected_0_value_cells(3,5)
add_surrounding_cells()
reveal_empty_cells()
print(booleangrid)
Ok, so I worked with your code for a bit, and I was able to make a code that works. I did adjust the grid size just to make it easier to figure out, but it should work for your original size. Just make sure you don't test with a grid of all 0s like in your posted code because it will return an error for too many recursions. Here's the code.
EDIT: I changed the code so now it reveals the surrounding numbers as well
# used to hold values to denote what the cell contains,
grid = [[0,1,2,5,4,6,0,0,0,0],
[0,1,2,5,4,6,0,0,0,0],
[0,1,2,5,4,6,0,0,5,0],
[0,1,2,5,4,6,0,0,0,0],
[0,1,2,5,4,6,0,0,0,0],
[0,1,2,5,4,6,6,0,0,0]]
# used to check what cell is hidden, true is hidden, false is revealed,
booleangrid = [[True for x in range(10)] for x in range(6)]
list_to_hold_tuples = []
def find_connected_0_value_cells(i,j):
list_to_hold_tuples.append((i,j))
if grid[i][j] == 0:
s = (i, j + 1)
t = (i, j - 1)
u = (i - 1, j - 1)
v = (i - 1, j)
w = (i - 1, j + 1)
x = (i + 1, j - 1)
y = (i + 1, j)
z = (i + 1, j + 1)
tempholding = [s, t, u, v, w, x, y, z]
for a in tempholding:
if a[0]>=0 and a[1]>=0 and a[0]<=len(grid)-1 and a[1]<=len(grid[i])-1 and grid[a[0]][a[1]]==0:
if (a[0]!=i and a[1]!=j) and (a not in list_to_hold_tuples):
find_connected_0_value_cells(a[0],a[1])
list_to_hold_tuples.append(a)
elif a[0]>=0 and a[1]>=0 and a[0]<=len(grid)-1 and a[1]<=len(grid[i])-1:
list_to_hold_tuples.append(a) #this part adds surrounding non-zero numbers
def reveal_empty_cells():
global booleangrid
for a,b in list_to_hold_tuples:
if a>=0 and a<len(booleangrid) and b>=0 and b<len(booleangrid[a]):
booleangrid[a][b] = False
for i in booleangrid:
print(i)
find_connected_0_value_cells(5,8)#Just using coordinates of 5,8 for testing, this would be click spot
reveal_empty_cells()