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.
Related
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
I wrote this simple python code but now I have to convert this into a class structure which accepts an iterator and act as a generator to yield the tuples(instead of return it should yield). I am unable to convert it:
def func(str,size):
size1 = size
list1 = []
for i in str:
list1.append(i)
if len(list1) < size1:
return (0)
continue
if len(list) > win_size1:
list1.pop(0)
min = min(list1)
return (min)
if __name__ == '__main__':
str = [1,2,3,4,5,6]
size = [4]
res = sol2(str,size)
Also I have to get the time and space complexity. In my view time complexity looks O(n)(I am not 100% confident though) but I am unable to determine space complexity.
How can I convert this code into a class with generator and what would be the time and space complexity?
Currently the continue statements which follow the return statements make no sense - continue will never be reached. However, you can yield each tuple with yield instead of return, e.g., replace
return (None,None,None,None)
with
yield (None,None,None,None)
Now the continue statement can actually be executed, and your algorithm can return more than one tuple.
Simply changing the returns into yields makes your function a generator.
I don't see any necessity to make this a "class structure". You can create a class and make sol2() a method of that class, but it's not clear why you should want to do that.
only the window1 and window2 will ask for extra space, so I think the space complexity will be O(n).
I'm trying to create a function that multiplies each item in a list and returns the total. The function doesn't stop running until memory runs out.
Can someone please explain to me why this isn't working?
items = [1,2,3,4,10]
def mult2(items):
if not items:
return 0
return mult2(items[0]) * mult2(items[1:])
mult2(items)
Couple of mistakes here
Your base case is wrong. The Base case has to be when the list is reduced to a single element and you need to return 1 and not 0.
You need to send a list with a single element and not the single element alone to meet your base case.
Corrected code
def mult2(items):
if len(items)==1:
return items[0]
return mult2([items[0]]) * mult2(items[1:])
Demo
>>> items = [1,2,3,4,10]
>>>
>>> def mult2(items):
... if len(items)==1:
... return items[0]
... return mult2([items[0]]) * mult2(items[1:])
...
>>> print(mult2(items))
240
There are two issues:
Single element is passed to mult2, but sequence is expected. That's why TypeError: 'int' object has no attribute '__getitem__' is raised, due to trying to subscripting int (code being executed resolves to 1[1:] which is simply not possible).
Your exit condition is broken. Neutral multiplier is 1, not 0.
After fixes your code would look like this:
def mult2(seq):
if not seq:
return 1
return seq[0] * mult2(seq[1:])
items = [1,2,3,4,10]
assert 240 == mult2(items)
You don't have a base case for your recursion that works properly.
Consider calling mult2 with [1,2,3] this gets to the return statement which called mult2 with 1 and with [1,2].
The problem is in the call to mult2 with the parameter 1 which is just an integer. When you get to the recursive part there's no indexing available because items is just an int at this point, so items[0] and items[1:] don't make sense at this point.
Fixed the errors in the OP, and this works:
items = [1,2,3,4,10]
def mult2(items):
if len(items) == 1:
return items[0]
return items[0] * mult2(items[1:])
print "sum:",mult2(items)
The question is use iterator to find the num from list who is greater than the nums in left and right
For example, select([0,1,0,2,0,3,0,4,0]) return [1,2,3,4]
My first try is
def select(iterable):
answer = []
it = iter(iterable)
try:
v2 = next(it)
while True:
v1,v2= v2,next(it)
if v2>v1 and v2>next(it):
answer.append(v2)
except StopIteration:
pass
return answer
This code fails.
I think the next(it) in the while loop would be the same iterator,but the next() still iter next one in the code.
then I change the code to below one, it works.
try:
v1,v2,v3 = next(it),next(it),next(it)
while True:
if v2>v1 and v2>v3:
answer.append(v2)
v1,v2,v3 = v2,v3,next(it)
except StopIteration:
pass
Can someone explain what is difference happen here?
There are two issues with the first snippet:
Every time you call next(it), it advances the iterator. You have to store the returned value if you want to access it more than once. Calling next(it) again won't do that; it will advance the iterator yet again.
Even if the first point weren't an issue, the following would still be problematic:
if v2>v1 and v2>next(it):
The issue here is short-circuit evaluation. Depending on whether v2>v1, this may or may not advance the iterator.
The error lies in this line:
if v2>v1 and v2>next(it):
Your calling next(it), but you don't store the return value. You just compare it to the v2. So the value gets skipped.
edit:
Btw, if you compare multiple values, the following comparison is much more cleaner:
if v1 < v2 > v3:
I am trying to run a sorting function recursively in python. I have an empty list that starts everything but everytime I try to print the list I get an empty list. here is my code. Any help would be greatly appreciated
def parse(list):
newParse = []
if len(list) == 0:
return newParse
else:
x = min(list)
list.remove(x)
newParse.append(x)
return sort(list)
The value of newParse is not preserved between invocations of the function; you're setting it equal to [] (well, you're creating a new variable with the value []).
Since the only time you return is
newParse = []
if len(list) == 0:
return newParse`
you will always be returning [] because that is the value of newParse at that time.
Because you are doing this recursively, you are calling the function anew, without keeping the function's own state. Take a moment to consider the implications of this on your code.
Instead of initialising newParse = [], add an optional parameter newParse defaulting to a bogus value, and set newParse = [] if you receive that bogus value for newParse. Otherwise, you'll actually be getting the same list every time (i.e. the contents of the list object are being mutated). And newParse through in your tail call.
You also seem to have the problem that your definition and and the supposedly-recursive call refer to different functions.
def sort(list, newParse = None):
if newParse is None:
newParse = []
if len(list) == 0:
return newParse
else:
x = min(list)
list.remove(x)
newParse.append(x)
return sort(list, newParse)
Here is what I think you are trying to do:
def recursive_sort(a_list):
def helper_function(list_to_be_sorted, list_already_sorted):
new = []
if len(list_to_be_sorted) == 0:
return list_already_sorted
else:
x = min(list_to_be_sorted)
list_to_be_sorted.remove(x)
new.append(x)
return helper_function(list_to_be_sorted, list_already_sorted + new)
return helper_function(a_list, [])
You shouldn't name variables list, as that is a builtin.
Also, if you are trying to implement a recursive sort function, you might want to look at quicksort, which is a very common (and fast) recursive sorting algorithm. What you have tried to implement is a recursive version of selection sort, which is much slower.
Also, if you actually need a sorting function, rather than just wanting to implement a recursive one, you should use the list method sort, or the function on an iterable sorted, both of which will be a lot faster than anything you could make in Python.