These two functions are returning different results. They look identical to me. What is going on here?
def DFS(r, c, grid):
if (r<0 or r>=len(grid) or c<0 or c>=len(grid[0])):
return False
if (grid[r][c] == 1):
return True
grid[r][c]=1
return DFS(r 1, c, grid) and DFS(r-1, c, grid) and DFS(r, c 1, grid) and DFS(r, c-1, grid)
and
def DFS(r, c, grid):
if (r<0 or r>=len(grid) or c<0 or c>=len(grid[0])):
return False
if (grid[r][c] == 1):
return True
grid[r][c] = 1
down = DFS(r 1, c, grid)
up = DFS(r-1, c, grid)
right = DFS(r, c 1, grid)
left = DFS(r, c-1, grid)
return down and up and right and left
For example in this code block,
for r in range(len(grid)):
for c in range(len(grid[0])):
if (grid[r][c] == 0):
#print("searching", r, c)
if (DFS(r, c, grid) == True):
print([r,c])
result =1
return result
The two DFS functions will return different values when given this input:
[[0,0,1,1,0,1,0,0,1,0],[1,1,0,1,1,0,1,1,1,0],[1,0,1,1,1,0,0,1,1,0],[0,1,1,0,0,0,0,1,0,1],[0,0,0,0,0,0,1,1,1,0],[0,1,0,1,0,1,0,1,1,1],[1,0,1,0,1,1,0,0,0,1],[1,1,1,1,1,1,0,0,0,0],[1,1,1,0,0,1,0,1,0,1],[1,1,1,0,1,1,0,1,1,0]]
Thank you for your help!
CodePudding user response:
The first version evaluates the last 4 calls to DFS using short-circuit evaluation: i.e., if the first DFS call in the return statement returns a falsey value, the and
operator won't even bother evaluating the next 3 DFS calls.
The last version explicitly evaluates all 4 DFS calls first, and only then evaluates the 4-way and
.
I'm guessing that has an impact on how often and when the grid[r][c] = 1
line is executed, which would explain why they behave differently.
CodePudding user response:
In the other answer there is a statement:
I'm guessing that has an impact on how often and when the
grid[r][c]=1
line is executed, which would explain why they behave differently.
This guess is right as proven by the code below where the second function is made equivalent to the first. The assert result_1 == result_2
not raising an assertion error shows that both functions work the same way now:
# These two functions are returning different results.
# They look identical to me. What is going on here?
def DFS1(r, c, grid):
if (r<0 or r>=len(grid) or c<0 or c>=len(grid[0])):
return False
if (grid[r][c] == 1):
return True
grid[r][c]=1
return DFS1(r 1, c, grid) and DFS1(r-1, c, grid) and DFS1(r, c 1, grid) and DFS1(r, c-1, grid)
# The functions in your question were not equivalent.
# The equivalent function to this above will be:
def DFS2(r, c, grid):
if (r<0 or r>=len(grid) or c<0 or c>=len(grid[0])):
return False
if (grid[r][c] == 1):
return True
grid[r][c] = 1
if down:= DFS2(r 1, c, grid):
if up:= DFS2(r-1, c, grid):
if right:= DFS2(r, c 1, grid):
if left:= DFS2(r, c-1, grid):
return True
# ^-- as (down and up and right and left) == True
return False
# ^-- as (down and up and right and left) == False
# For example in this code block,
result_1 = 0
grid = [[0,0,1,1,0,1,0,0,1,0],[1,1,0,1,1,0,1,1,1,0],[1,0,1,1,1,0,0,1,1,0],[0,1,1,0,0,0,0,1,0,1],[0,0,0,0,0,0,1,1,1,0],[0,1,0,1,0,1,0,1,1,1],[1,0,1,0,1,1,0,0,0,1],[1,1,1,1,1,1,0,0,0,0],[1,1,1,0,0,1,0,1,0,1],[1,1,1,0,1,1,0,1,1,0]]
for r in range(len(grid)):
for c in range(len(grid[0])):
if (grid[r][c] == 0):
#print("searching", r, c)
if (DFS1(r, c, grid) == True):
print([r,c])
result_1 =1
result_2 = 0
print(' --- ' )
grid = [[0,0,1,1,0,1,0,0,1,0],[1,1,0,1,1,0,1,1,1,0],[1,0,1,1,1,0,0,1,1,0],[0,1,1,0,0,0,0,1,0,1],[0,0,0,0,0,0,1,1,1,0],[0,1,0,1,0,1,0,1,1,1],[1,0,1,0,1,1,0,0,0,1],[1,1,1,1,1,1,0,0,0,0],[1,1,1,0,0,1,0,1,0,1],[1,1,1,0,1,1,0,1,1,0]]
for r in range(len(grid)):
for c in range(len(grid[0])):
if (grid[r][c] == 0):
#print("searching", r, c)
if (DFS2(r, c, grid) == True):
print([r,c])
result_2 =1
# These two DFS functions above will return the same values.
assert result_1 == result_2