I have a problem with the recursion. The function I wrote should recursively generate and return a list of pairs, called chain. The breaking condition is when the pair, (remainder, quotient) already belongs to the chain-list, then stop iterating and return the list. Instead of completing, the recursion just blows up, raising a RecursionError. The list doesn't update and contains only a single term, so the breaking condition is not executed. I don't understand why...
How should I proper implement the recursive step to make the list update?
def proper_long_division(a, b):
"""a < b"""
chain = []
block_size = len(str(b)) - len(str(a))
a_new_str = str(a) + '0' * block_size
a_new = int(a_new_str)
if a_new < b:
a_new = int(a_new_str + '0')
quotient = a_new // b
remainder = a_new - b * quotient
print(remainder)
#print(chain)
# breaking condition <--- !
if (remainder, quotient) in chain:
return chain
# next step
chain.append((remainder, quotient))
chain.extend(proper_long_division(remainder, b))
return chain
try:
a = proper_long_division(78, 91)
print(a)
except RecursionError:
print('boom')
Here a an example of recursion which (should) follows the same structure but the returned list is updated. I don't know why one code works while the other does not.
import random
random.seed(1701)
def recursion():
nrs = []
# breaking condition
if (r := random.random()) > .5:
return nrs
# update
nrs.append(r)
# recursive step
nrs.extend(recursion())
return nrs
a = recursion()
print(a)
# [0.4919374389681155, 0.4654907396198952]
When you enter proper_long_division, the first thing you do is chain = []. That means that the local variable chain refers to a new empty list. Then you do some algebra, which does not affect chain, and check if (remainder, quotient) in chain:. Clearly this will always be False, since chain was and has remained empty.
The next line, chain.append((remainder, quotient)) runs just fine, but remember that only this call to proper_long_division has a reference to it.
Now you call chain.extend(proper_long_division(remainder, b)). You seem to expect that the recursive call will be able to check and modify chain. However, the object referred to by chain in a given call of proper_long_division is only visible within that call.
To fix that, you can use a piece of shared memory that any invocation of the recursive function can see. You could use a global variable, but that would make the function have unpredictable behavior since anyone could modify the list. A better way would be to use a nested function that has access to a list in the enclosing scope:
def proper_long_division(a, b):
"""a < b"""
chain = {}
def nested(a, b):
while a < b:
a *= 10
quotient = a // b
remainder = a - b * quotient
key = (remainder, quotient)
if key in chain:
return chain
# next step
chain[key] = None
nested(remainder, b)
nested(a, b)
return list(chain.keys())
A couple of suggested changes are showcased above. Multiplication by 10 is the same as padding with a zero to the right, so you don't need to play games with strings. Lookup in a hashtable is much faster than a list. Since ordering is important, you can't use a set. Instead, I turned chain into a dict, which is ordered as of python 3.6, and used only the keys for lookup. The values all refer to the singleton None.
The second example does not match the structure of the first in the one way that matters: you do not use nrs as part of your exit criterion.
Related
I have a recursive algorithm in which I calculate some probability values. The input is a list of integers and a single integer value, which represents a constant value.
For instance, p([12,19,13], 2) makes three recursive calls, which are
p([12,19],0) and p([13], 2)
p([12,19],1) and p([13], 1)
p([12,19],2) and p([13], 0)
since 2 can be decomposed as 0+2, 1+1 or 2+0. Then each call follows a similar approach and makes several other recursive calls.
The recursive algorithm I have
limit = 20
def p(listvals, cval):
# base case
if len(listvals) == 0:
return 0
if len(listvals) == 1:
if cval == 0:
return listvals[0]/limit
elif listvals[0] + cval > limit:
return 0
else:
return 1/limit
result = 0
for c in range(0,cval+1):
c1 = c
c2 = cval-c
listvals1 = listvals[:-1]
listvals2 = [listvals[-1]]
if listvals[-1] + c2 <= limit:
r = p(listvals1, c1) * p(listvals2, c2)
result = result+r
return result
I have been trying to convert this into a bottom up DP code, but could not figure out the way I need to make the iteration.
I wrote down all the intermediate steps that are needed to be calculated for the final result, and it is apparent that there are lots of repetitions at the bottom of the recursive calls.
I tried creating a dictionary of pre-calculated values as given below
m[single_value]=[list of calculated values]
and use those values instead of making the second recursive call p(listvals2, c2), but it did not help much as far as the running time is concerned.
How can I improve the running time by using a proper bottom-up approach?
Not sure that I understand what your program wants to compute, so can't help on that, maybe explain a bit more?
Regarding improving performance, you are caching only the leaf nodes of the computations that are repeated in recursive calls. A better way to do that would be have the first parameter of your function p as a tuple instead of a list, and then use tuple of both the arguments to p as caching keys in the dictionary.
Python's standard library functools provides a simple way to do this fairly common piece.
from functools import wraps
def cached(func):
cache = {}
#wraps(func)
def wrapped(listvals, cval):
key = (listvals, cval)
if key not in cache:
cache[key] = func(key)
return cache[key]
return wrapped
Use this decorator to cache all calls function:
#cached
def p(listvals, cval):
Now have your p take tuple instead of list:
p((12,19,13), 2)
My parameter, n is a phone number as an integer.
Using recursion I want to return the first three numbers in the integer.
I've turned the integer into a list of individual number characters and I'm attempting to delete the last number over and over again until I'm left with the last three, but I'm stuck on how to repeat it.
def areaCodes(n):
n = str(n)
n = list(n)
del n[-1]
#n = reduce(opperator.add, n)
n = ''.join(n)
n = int(n)
return n
I know I'm supposed to repeat the name in the return somehow, but because n isn't an integer that I can use to repeat. What do I do?
How about something like this?
def areaCodes(n):
# if n is less than 1000, what does it mean about the number of digits?
if n < 1000:
return # fill...
# otherwise, if n is greater than 1000, how can we alter n to remove the last
# digit? (hint: there's an operation similar to division called f...r division)
return areaCodes( # operate on n somehow...)
I assume that this is an exercise where recursion is necessary. If so, try this (there are better ways to accomplish your end goal, but I tried to modify your existing code as little as possible):
def areaCodes(n):
n_lst = list(str(n))
del n_lst[-1]
n_str = ''.join(n_lst)
n_int = int(n_str)
if len(n_lst) > 3:
return areaCodes(n_int)
return n_int
This will call the function again if the length of the number is greater than three, and return the number otherwise. Basically, the only part you were missing in your original function was the following, which is the recursive part:
if len(n_lst) > 3:
return areaCodes(n_int)
Remember that for a function to be recursive, it will have two main attributes:
It will at some point call itself. (this is what makes it 'repeat')
It will have some stopping condition (or base case).
You mentioned #1 when you wrote that you're supposed to use "the name in the return," so that's great! You just need to write that in your code:
return areaCodes(n), Where n is the updated phone number with a digit removed.
As you can see, each recursive call should do some work towards the solution, and should pass its mini-solution to the next recursive call.
Along with #2 above, you need to specify a base case, where the recursion will cease. So, since you're taking away a digit each time you call your function, you should include some kind of check to see if the current input is the length you want yet.
If it is the right length, you're done, and you should return the current number (not another recursive call).
Otherwise, you aren't done with the recursion yet.
import sys
def areaCodes(n):
#Create a list
myList = list(str(n))
#Delete last element
del myList[-1]
#Combine your elements into string list
myListStr = ''.join(myList)
#Type cast to int
myListInt = int(myListSte)
#Check whether your list satisfies your condition
if len(myList) > 3:
#Recusivley call the function again
return areaCodes(myListInt)
#Return your list when recursion completes
return myListInt
n = 12345
print areaCodes(n)
I'm doing a Merge Sort assignment in Python, but I keep have the error of RuntimeError: maximum recursion depth exceeded
Here's my code:
def merge_sort(list):
left_num = len(list) // 2
left_sorted = merge_sort(list[:left_num])
right_sorted = merge_sort(list[left_num:])
final_sort = merge(left_sorted, right_sorted)
return final_sort
def merge(left_sorted, right_sorted):
final_sort = []
while left_sorted and right_sorted:
if left_sorted[0] <= right_sorted[0]:
final_sort.append(left_sorted[0])
left_sorted.pop(0)
else:
final_sort.append(right_sorted[0])
right_sorted.pop(0)
final_sort = final_sort + left_sorted + right_sorted
return final_sort
if __name__ == "__main__":
list = [4, 2]
print(merge_sort(list))
Can someone tell me why? To make the problem more usable to others, feel free to edit the question to make it make more sense. ^_^
When you write a recursive function, you should be careful about the base case, which decides when the recursion should come to an end.
In your case, the base case is missing. For example, if the list has only one element, then you don't have recursively sort it again. So, that is your base condition.
def merge_sort(list):
if len(list) == 1:
return list
...
...
Note: The variable name list shadows the builtin function list. So better avoid using builtin names.
Since you are doing lot of pop(0)s, its worth noting that it is not efficient on lists. Quoting Python's official documentation,
Though list objects support similar operations, they are optimized for fast fixed-length operations and incur O(n) memory movement costs for pop(0) and insert(0, v) operations which change both the size and position of the underlying data representation.
So, the better alternative would be to use collections.deque, instead of list, if you are popping a lot. The actual popping from a deque is done with popleft method.
>>> from collections import deque
>>> d = deque([4, 2])
>>> d.popleft()
4
>>> d
deque([2])
You don't have an exit point in merge_sort. You need to do something like:
left_num = len(list) // 2
if left_num <= 1:
return list
You always need to have a conditional exit in recursion function: if COND then EXIT else RECURSION_CALL.
Is it always possible to convert a recursion into a tail recursive one?
I am having a hard time converting the following Python function into a tail-recursive one.
def BreakWords(glob):
"""Break a string of characters, glob, into a list of words.
Args:
glob: A string of characters to be broken into words if possible.
Returns:
List of words if glob can be broken down. List can be empty if glob is ''.
None if no such break is possible.
"""
# Base case.
if len(glob) == 0:
return []
# Find a partition.
for i in xrange(1, len(glob) + 1):
left = glob[:i]
if IsWord(left):
right = glob[i:]
remaining_words = BreakWords(right)
if remaining_words is not None:
return [left] + remaining_words
return None
I'n not sure if is always the case, but most of recursive functions can be implemented as tail recursives. Besides Tail Recursion is different from Tail Recursion optimization.
Differences Tail Recursion and "Regular" ones
There are two elements that must be present in a recursive function:
The recursive call
A place to keep count of the return values.
A "regular" recursive function keeps (2) in the stack frame.
The return values in regular recursive function are composed of two types of values:
Other return values
Result of the owns function computation
Let's see a example:
def factorial(n):
if n == 1 return 1
return n * factorial(n-1)
The frame f(5) "stores" the result of it's own computation (5) and the value of f(4), for example. If i call factorial(5), just before the stack calls begin to colapse, i have:
[Stack_f(5): return 5 * [Stack_f(4): 4 * [Stack_f(3): 3 * ... [1[1]]
Notice that each stack stores, besides the values i mentioned, the whole scope of the function. So, the memory usage for a recursive function f is O(x), where x is the number of recursive calls i have to made. So, if i needb 1kb of RAM to calculate factorial(1) or factorial(2), i need ~100k to calculate factorial(100), and so on.
A Tail Recursive function put (2) in it's arguments.
In a Tail Recursion, i pass the result of the partial calculations in each recursive frame to the next one using parameters. Let's see our factorial example, Tail Recursive:
def factorial(n):
def tail_helper(n, acc):
if n == 1 or n == 2: return acc
return tail_helper(n-1, acc + n)
return tail_helper(n,0)
Let's look at it's frames in factorial(4):
[Stack f(4, 5): Stack f(3, 20): [Stack f(2,60): [Stack f(1, 120): 120]]]]
See the differences? In "regular" recursive calls the return functions recursively compose the final value. In Tail Recursion they only reference the base case (last one evaluated). We call accumulator the argument that keeps track of the older values.
Recursion Templates
The regular recursive function go as follows:
def regular(n)
base_case
computation
return (result of computation) combined with (regular(n towards base case))
To transform it in a Tail recursion we:
Introduce a helper function that carries the accumulator
run the helper function inside the main function, with the accumulator set to the base case.
Look:
def tail(n):
def helper(n, accumulator):
if n == base case:
return accumulator
computation
accumulator = computation combined with accumulator
return helper(n towards base case, accumulator)
helper(n, base case)
Your example:
I did something like this:
def BreakWords(glob):
def helper(word, glob, acc_1, acc_2):
if len(word) == 0 and len(glob) == 0:
if not acc_1:
return None
return acc
if len(word) == 0:
word = glob.pop[0]
acc_2 = 0
if IsWord(word.substring[:acc_2]):
acc_1.append(word[:acc_2])
return helper(word[acc_2 + 1:], glob, acc_1, acc_2 + 1)
return helper(word[acc_2 + 1:], glob, acc_1, acc_2 + 1)
return helper("", glob, [], 0)
In order to eliminate the for statement you made, i did my recursive helper function with 2 accumulators. One to store the results, and one to store the position i'm currently trying.
Tail Call optimization
Since no state is being stored on the Non-Border-Cases of the Tail Call stacks, they aren't so important. Some languages/interpreters then substitute the old stack with the new one. So, with no stack frames constraining the number of calls, the Tail Calls behave just like a for-loop.
But unfortunately for you Python isn't one of these cases. You'll get a RunTimeError when the stack gets bigger than 1000. Mr. Guido
thinks that the clarity lost to debugging purposes due to Tail Call Optimization (caused by the frames thrown awy) is more important than the feature. That's a shame. Python has so many cool functional stuff, and tail recursion would be great on top of it :/
I'm trying to halt the for loop below once values (x,y) or (z,2) have been returned so that the value i doesn't keep increasing, and simply halts when the if or elif condition is first
def maxPalindrome(theList):
# students need to put some logic here
maxcomplist = theList[:]
maxcomplist.reverse()
control = len(theList) - 1
# exit if maxPalindrome is True
for i in range(control):
if maxcomplist[:] == theList[:]:
x = 0
y = len(theList)
return (x, y)
break
elif maxcomplist[i:control] == theList[i:control]:
successList = theList[i:control]
z = i
w = len(theList) - z - 1
return (z, w)
How can I accomplish this?
As I wrote in a comment already: that function isn't a recursive one at all.
Recursion means, that a function calls itself to complete it's purpose. This call can be indirect, meaning that the function uses helper function that will call the first function again.
But your code doesn't cover both cases.
A recursive function always have a certain architecture:
the first thing after being called should be to test, if the primitive case (or one primitive case among options) has been reached. if so, it returns.
If not it will compute whatever is needed and pass this results to itself again,
untill the primitive case is reached, and the nested function calls will finish in one after the other.
One well-known usage of recursion is the quicksort algorithm:
def quicksort(alist):
if len(alist) < 2:
return alist # primitive case: a list of size one is ordered
pivotelement = alist.pop()
# compute the 2 lists for the next recursive call
left = [element for element in alist if element < pivotelement]#left = smaller than pivotelemet
right = [element for element in alist if element >= pivotelement]#left = greater than pivotelemet
# call function recursively
return quicksort(left) + [pivotelement] + quicksort(right)
So the "stop" must be the return of a primitive case. This is vital for recursion. You cannot just break out somehow.
I don't understand the question - if I get it right, that what you want already happens. If you return, the function stops running.
Some comments in addition to this answer:
As well, I cannot see where the function is called recursively, nor what
exit if maxPalindrome is True
means. (Is this a comment, maybe?)
Besides, the maxcomplist[:]==theList[:] does not make much sense to me, and seem to be a waste of time and memory, and to have this comparison in each iteration loop doesn't make it faster as well.