I am trying to write a function which enables a move 1 unit to the left (in the x-axis) in a grid. It should only work if there is a valid coordinate to the left, and if not (i.e. the start point is on the edge of the grid), the function should return None. Here is my attempt:
def left_move(point):
try:
LEFT = grid[point[1]][point[0]-1]
except IndexError:
return None
if LEFT == '.':
change = [-1,0]
for idx, amount in enumerate(change):
point[idx]+=amount
return point
return None
Say the starting point is [0,3] and therefore on the edge of the grid and I only run the top part of the code:
def left_move(point):
try:
LEFT = grid[point[1]][point[0]-1]
except IndexError:
return None
It returns None as expected. But if the whole block is executed it returns [-1,3] which is outside of the grid and shouldn't be allowed by the try-except . Why is this? And how can it be corrected?
This is because Python's interpretation of -1 in array indexing is the last element of the array. -1 is a legal way of referencing array elements and thus will not trigger an IndexError exception.
>>> a = [0,1,2]
>>> print a[-1]
2
You would need to manually check if the value you are given resolves to -1 and then handle that accordingly.
Here, you need to place the rest of the code inside the try statement. Otherwise, it will try, fail, and then run the rest of the code.
def left_move(point):
if point[0]-1 != -1:
LEFT = grid[point[1]][point[0]-1]
if LEFT == '.':
change = [-1,0]
for idx, amount in enumerate(change):
point[idx]+=amount
return point
return None
else:
return None
Related
So, Im trying to print the largest number in the array alongside its index so example [1,4] but I am trying to return none when the array is blank. But nothing is being outputted to the screen.
def Largest(Array):
Array = []
if Array == []:
return None
largest = 0
for x in range(0, len(Array)):
if(Array[x] > largest):
largest = A[x]
index = Array.index(Array[x])
B = [largest, index]
return (B)
When I run the function Largest(Array) in the terminal, nothing is printed.
Interactive Python REPLs don't print the return value of a function when it returns None, because that's what functions that don't return anything return by default.
So if you want to see the return value in cases like this, you need to call print() explicitly.
print(Largest([]))
So I came across an exercise problem in one of my CSE 101 slides and the problem asked to find a value in a list or a string using recursion. If the value was inside the list or the string, return the first index position that matches the value. I was able to solve it but I don't understand why it works. Here is my code:
def rindex(a, pos):
if pos not in a:
return None
elif pos in a:
if a[0] != pos:
return rindex(a[1:], pos) + 1
return 0
Specifically, I don't understand why
return 0
makes my function work. Why does it return the correct value rather than 0?
Every time a return is encountered in your function the result is returned and the function execution stops. This means that return 0 will never be encountered in the event of pos existing in the current a slice except when the first element of the current slice equals to pos - at that point you return 0 to indicate that the index should not be increased. If you were not to return it, rindex() would return None by default causing an error when you try to sum it with + 1 up the recursion chain.
That being said, whenever you do if pos not in a: you're iterating over the list a in search of pos so your code will be immensely inefficient (especially since you're then doing the exact same search again in the elif block whereas simple else would more than suffice). You can reformulate your code as:
def rindex(a, pos):
if a[0] == pos: # element found, do not increase the index
return 0
return rindex(a[1:], pos) + 1
So you're only doing slices instead of two iterations on each recursion. The biggest issue here is that it will raise an IndexError if pos is not found as the list recursion reaches the end. You can capture that and return any sort of value if you prefer value returns over exceptions, so in your case:
def rindex(a, pos):
if a[0] == pos: # element found, do not increase the index
return 0
try:
return rindex(a[1:], pos) + 1
except (IndexError, TypeError): # capture both to propagate
return None
However, keep in mind that even doing list slices is not the most perfomant solution, especially when memory is concerned. Since Python passes names to references you can recurse over your whole list instead with little to no penalty and use indexes to traverse over the list recursively, i.e.:
def rindex(a, pos, loc=0):
if a[loc] == pos:
return loc
return rindex(a, pos, loc+1)
And you don't even have to do a recursive try .. except choreography to capture the errors - you can do it directly in the function either preemptive (LBYL style):
def rindex(a, pos, loc=0):
if len(a) >= loc:
return None
if a[loc] == pos:
return loc
return rindex(a, pos, loc + 1)
Or after the fact (EAFP style):
def rindex(a, pos, loc=0):
try:
if a[loc] == pos:
return loc
except IndexError:
return None
return rindex(a, pos, loc + 1)
These also allow you to pass an arbitrary index as well (i.e. -1) when element is not-found as the validation is separated from the actual index search so it wont affect the index sum.
I have a function that its called recursively. When I run it I get the error "maximum recursion depth exceeded while calling a Python object"
How can increase the limit on mac? If I use the following, I get the error "cannot increase the limit on mac"
resource.setrlimit(resource.RLIMIT_STACK, (2**24,-1))
sys.setrecursionlimit(10**6)
I had a problem where I had the possibility of recurring several billions of times, and the way I did it was by flattening the recursion. I don't know if this method has been documented before, because I came up with it on my own instead of finding it. All you really have to do is put the local namespace of each function in a list. This will require a change in your actual code, if there is no workaround. Here's how it works:
Say I have this function:
def flatten_a_list(obj):#[[6,5],7,[3,[9,0]]] -> [6,5,7,3,9,0]
flattened = []
for item in obj:
if type(item) == list:
flattened.append(flatten_a_list(item))
else:
flattened.append(item)
return flattened
Now, this is traditionally recursive. To make it so that it will work for however many nestings there are with no limit, I would do this:
from copy import deepcopy
def improved(obj):#[[6,5],7,[3,[9,0]]] -> [6,5,7,3,9,0]
flattened = []
position = [0]
while True:
print('position: {}'.format(str(position)))
x = deepcopy(obj)
try:
for index in position:
x = x[index]
except (IndexError, TypeError):
break
if type(x) == list:
position.append(0)
print('continuing')
continue
else:
flattened.append(x)
#Test the next position
test = deepcopy(position)
test[-1] += 1
x = deepcopy(test)
print('x: {}'.format(x))
try:
y = deepcopy(obj)
for index in x:
y = y[index]
position = deepcopy(test)
except (IndexError, TypeError):
position = position[:-1]
try:
position[-1] += 1
except IndexError:
break
return flattened
Two words: Mind Bending
The function I wrote works fine, but it is unoptimized. If you want speed, first make sure you understand the function, then combine the checkings of index overflow by taking the 'x' and 'y' blocks of code are polymorphesizing them.
You will have to adapt this to your code, but as long as you understand it, it shouldn't be much or a problem. Plus, the answer is cross platform and unlimited.
I am trying to write a function which is supposed to compare list structures (the values are indifferent). The problem is that I have two lists which are unequal but the function still returns True even though it actually goes into the else part. I don't understand why and what I did wrong. Here is my code:
def islist(p): #is p a list
return type(p)==type(list())
def ListeIsomorf(a,b):
if len(a)==len(b):
for i,j in zip(a,b):
if islist(i) and islist(j):
ListeIsomorf(i,j)
elif islist(i) or islist(j):
return(False)
return(True)
else:
print(a,"length from the list isn't equal",b)
return(False)
#example lists
ListeE = [[],[],[[]]]
ListeD = [[],[],[[]]]
ListeF = [[[],[],[[]]]]
ListeG = [[],[[]],[[]]]
ListeH = [1,[3]]
ListeI = [1,3]
#tests
print(ListeIsomorf(ListeD,ListeE)) # True
print(ListeIsomorf(ListeD,ListeF)) # False
print(ListeIsomorf(ListeD,ListeG)) # False
print(ListeIsomorf(ListeH,ListeI)) # False
So the problem only occurs with the third print(ListeIsomorf(ListeD,ListeG)) # False. It actually goes into the else part and does print the "length from the list isn't equal" but it doesn't stop and it doesn't give out the return(False). Am I missing something?
The problem is that when your function calls itself recursively:
ListeIsomorf(i,j)
it ignores the returned value.
Thus the comparisons that take place at the second level of recursion have no effect on what the top level returns.
Changing the above to:
if not ListeIsomorf(i,j):
return(False)
fixes the problem.
My sudoku solver does exactly what it's supposed to do - except returning the correct thing. It prints what it should right before the return (a correctly solved grid), but then it seems to keep running for a bit and returns None. I can't figure out what's going on.
Grid is a list of lists. Assume that check_sudoku returns True if the grid is valid (solved or not), and False otherwise.
def solve_sudoku(grid, row=0, col=0):
"Searches for valid numbers to put in blank cells until puzzle is solved."
# Sanity check
if not check_sudoku(grid):
return None
# Sudoku is solved
if row > 8:
return grid
# not a blank, try next cell
elif grid[row][col] != 0:
next_cell(grid, row, col)
else:
# try every number from 1-9 for current cell until one is valid
for n in range(1, 10):
grid[row][col] = n
if check_sudoku(grid):
next_cell(grid, row, col)
else:
# Sudoku is unsolvable at this point, clear cell and backtrack
grid[row][col] = 0
return
def next_cell(grid, row, col):
"Increments column if column is < 8 otherwise increments row"
return solve_sudoku(grid, row, col+1) if col < 8 else solve_sudoku(grid, row+1, 0)
You're calling next_cell in the recursion, but never returning its value.
It seems to me like this will never actually return something useful. The first time we enter your solve_sudoku, you check to see if the grid is solved, and if so you return it. After that, you begin a bunch of recursion which ultimately will end up coming back out towards the end of the function and returning None. No matter what, you are returning None all the time. The only thing that you end up with is a modified grid argument that you passed in to start.
def solve_sudoku(grid, row=0, col=0):
# possible return at the first entry point
if not check_sudoku(grid):
return None
# only time you would ever NOT get None
if row > 8:
return grid
...recurse...
# come back out when the stack unwinds,
# and there is no return value other than None
What I speculate is happening, is that you are printing the values along the way, and you do properly see a solved grid at the moment it happens, but your function isn't set up to properly completely break out when that is done. It continues to loop around until it exhausts some range and you see a bunch of extra work.
The important thing to do is to check the return value of the recursive call. You would either return None if its not solved, or grid if it is. As it stands, you never care about the result of your recursions in the calling scope.
Because I don't have all the details about your specific code, here is a simple equivalent:
def solver(aList):
if aList[0] == 10:
print "SOLVED!"
return None
print "NOT SOLVED..."
return next(aList)
def next(aList):
# do some stuff
# check some stuff
aList[0] += 1
return solver(aList)
if __name__ == "__main__":
data = [0]
solver(data)
print data
Notice that the indirectly recursive call to checker() -> solver() has its value returned all the way up the chain. In this case we are saying None means solved, and otherwise it should keep recursing. You know that at some point deep in your recursion stack, the solution will be solved. You will need to communicate that back up to the top right away.
The communication looks like this:
aList == [0]
solver(aList)
next(...)
next(...)
next(...)
next(...)
#SOLVED
<- next(...)
<- next(...)
<- next(...)
<- next(...)
<-solver(aList)
aList == [10]
And here is what your version might look like if applied to my simple example:
aList == [0]
solver(aList)
next(...)
next(...)
# SOLVED
next(...)
next(...)
...
<- next(...)
<- next(...)
<- next(...)
<- next(...)
<-solver(aList)
aList == [10]