How to write a recursive function in python - python

I have been stuck on the solution to this question for quite a while i have written a piece of code that works as requested but i seems to get an error at the end of the compilation
You need to design an iterative and a recursive function called
replicate_iter and replicate_recur respectively which will receive two
arguments: times which is the number of times to repeat and data which
is the number or string to be repeated.
The function should return an array containing repetitions of the data
argument. For instance, replicate_recur(3, 5) or replicate_iter(3,5)
should return [5,5,5]. If the times argument is negative or zero,
return an empty array. If the argument is invalid, raise a ValueError.
my code is as below:
def replicate_iter(times,data):
emptyArray = []
if not isinstance(data, int) and not isinstance(data, str):
raise ValueError
if times <= 0:
print emptyArray
if not isinstance(times,int):
raise ValueError
else:
while times > 0:
emptyArray.append(data)
times -= 1
return emptyArray
array = []
def replicate_recur(times,data):
if not isinstance(data,int) and not isinstance(data,str):
raise ValueError
if not isinstance(times,int):
raise ValueError
if times <= 0 and len(array) != 0:
return array
elif times <= 0 and len(array) <=0:
return []
else:
array.append(data)
replicate_recur(times - 1,data)
Kindly assist with suggestions please
error message :

First, think about this:
def f(times,data):
return [] if times == 0 else f(times - 1,data) + [data]
print(f(3,5)) # [5,5,5]
Now, with regard to your recursive solution, (1) in order to access array, replicate_recur would need a declaration at its outset, "global array," since the variable, array, is declared outside of the function's scope; and (2) modify the recursive call, "replicate_recur(times - 1,data)," to "return replicate_recur(times - 1,data)," in order for the function to actually return a value when times is greater than zero. (That said, as I understand, it's generally considered undesirable form to have global accumulators for recursive functions.)

Maybe this is what you want based on the example you gave:
array = []
def replicate_recur(times, val):
if(isinstance(times, int) and times > 0):
array.append(val)
return replicate_recur(times-1, val)
return array
print(replicate_recur(3, 5)) # [5,5,5]
array = []
def replicate_iter(times, val):
if(isinstance(times, int) and times > 0):
for i in range(times):
array.append(val)
return array
raise ValueError
print(replicate_iter(3, 5)) #[5,5,5]

You must not use a global variable. A second call to your function leads to wrong results. Use a internal function or optional parameter instead.
def replicate_recur(times,data, array=None):
if array is None:
array = []
if times <= 0:
return array
array.append(data)
return replicate_recur(times - 1, data, array)

Maybe you should split up the logic, always becomes more readable, so it becomes easier to implement. You should avoid global variables, especially global lists, they will cause you much pain.
def rep_rec(times, data, pack=[]):
pack += [data]
return pack if times < 2 else rep_rec(times-1, data, pack)
def replicate_recur(times, data):
if not times or not data:
return []
if isinstance(times, int) and (isinstance(data, int) or isinstance(data, str)):
return rep_rec(times, data) if times > 0 else []
raise ValueError

"""
A. In recursions, in general, some input is minimized until some minimum condition.
"eg: in f(x-2), x is the input"
B. In the following recursion, multiples of x "eg: x TIMES f(x-2)" are
computed as x gets smaller and smaller by 2 "eg: f(x MINUS 2)",
until x finally reaches 1 "eg: if x==ONE return 1", the minimum CONDITION value.
C. The recursion multiplies by many values generated by calls of function "f",
until mininum is reached.
"eg: x TIMES value-AT-f-CALL_a(x-2) TIMES value-AT-f-CALL_b(x-2)....
D. When mininum CONDITION is reached, or in other words, when x reaches 1, the recursion
multiplies by 1, instead of another value generated by function "f" call.
"eg: x TIMES value-AT-f-CALL_a(x-2) TIMES value-AT-f-CALL_b(x-2) TIMES 1"
NOTE: This is why the recursion ends, as it no longer multiplies by value at f-call.
E. In "TIMES 1" in D above, because 1 is the minimum RETURN value
"eg: if x==1: return ONE", this means the minimum CONDITION is reached.
NOTE: if we had x PLUS f(x-2), then the mininum value would be
ADDED TO (instead of multiplied by) the SUM (instead of the product).
"""
def f(x):
"""This is a recursive function f to generate product of x, as x decreases by 2"""
if x == 1:
return 1
else:
return (x * f(x-2))

Related

Inconsistent return value Pylint

I have used pylint to check my code and I am receiving the following suggestion.
'Either all return statements in a function should return an expression, or none of them should. (inconsistent-return-statements)'. The code block is below. I am passing in a value and need to return which value range it belongs to. If I move the return value outside of the if it will return the incorrect count value. Any suggestions?
def findRangeValue(ranges, number):
count = -1
n = 2
for x in range(len(ranges)-n+1):
count += 1
batch = range[x:x + n]
if batch[0] < number <= batch[1]:
return count
You need confirm the function always have a non-empty (not None) return value in most common situation.
Your code will return None when all if statement in the loop failed, need add a final return value outside loop.
example code:
def findRangeValue(ranges, number):
count = -1
n = 2
for x in range(len(ranges)-n+1):
count += 1
batch = ranges[x:x + n]
if batch[0] < number <= batch[1]:
return count
return -1
print(findRangeValue([1,3,5,7,9], 4))
print(findRangeValue([1,3,5,7,9], 10))
result:
1
-1
Your function is written in a way, that it returns a value only if a condition is met i.e .
if batch[0] < number <= batch[1]:
Assume a situation you are consuming the function something like
range_val = findRangeValue([1,2,3], 3)
If the condition was met the return value will be assigned to range_val. But if the condition was not met, then the function returns nothing and your range_val becomes None.
But your code expects it to be a number and not None. So, now you need to check the return value to avoid errors - an extra line of code.
Assume you are calling this function from various parts of your code, every where you need to bring in this check - more and more code.
To avoid this, a standard to follow is that, a function always returns what was promised. If it was not able to do so, raise an Exception so that, the caller is notified without an additional check.
In your particular scenario, you can use a break statement and always return a count outside (beware, if break was not met, the value could be not what you expect) Or use an additional flag variable with break, and raise an error if the flag variable was not set.

Understanding the code behind a gridtraveller

I found a basic code in python to find the numbers of paths you can take in a (m,n) grid if you can only go either down or right.
def gridtraveller(m,n):
if m == 0 or n == 0:
return 0
elif m == 1 or n == 1:
return 1
return gridtraveller(m-1,n) + gridtraveller(m,n-1)
But I dont understand why is this working for two thing:
What does def something (m,n) do ?
And why does here we return the definition ? ( I do understand why we return
m-1 and n-1 , but I don't understant the concepte of a def returning a def)
Thanks to you and sorry english is not my first language.
In Python the def keyword is simply used to define a function, in this case it's the function gridtraveller(m,n). What you're seeing with that last return statement is actually a function returning the value of another function. In this case it's returning the value of another call to gridtraveller, but with different parameter values; this is called recursion. An important part of recursion is having appropriate base cases, or return values that won't end in another recursive call(i.e. the return 0 or return 1 you see).
It can be easier to understand by simply stepping through a few iterations of the recursive calls. If your first function call starts with m = 2 and n = 1, the first call will end with return gridtraveller(1,1) + gridtraveller(2,0). The first call in that statement will then return 1 since either m or n are 1 and the second returns 0 since n = 0 here giving a total result of 1. If larger values of m and n are used it will obviously result in a higher number since more calls to gridtraver(m,n) will happen.

How to get minimum odd number using functions from list

I'm trying to get the minimum odd number using python. I used lambda, loops and other methods to get minimum odd number but i was not able to get that using functions. here is my code
z= [1,8,-4,-9]
def min_odd(x):
for i in x:
if (i%2!=0):
return min(i)
y = min_odd(z)
print (y)
Can some please tell me what i was missing here.
The min() function expects an iterable like a list which it will then yield the smallest element from.
E.g. min([1,0,3]) gives 0.
So if you want to use it, you must create a list (or other iterable) of the odd numbers that you can then pass into it:
def min_odd(x):
odds = []
for i in x:
if i % 2 != 0:
odds.append(i)
return min(odds)
note that we could also use a list-comprehension:
def min_odd(x):
return min([i for i in x if i % 2 != 0])
which both work.
An alternative method would be to store the current minimum odd value in a variable and update this variable if we come across a smaller odd value:
def min_odd(x):
min_v = float('inf')
for i in x:
if i % 2 != 0 and i < min_v:
min_v = i
return min_v
Try:
min([val for val in z if val % 2 != 0])
It seems your code logics are wrong. First off, you seem to have an indentation error in the return statement. Second off, the min() function requires a collection of items (like an array for example) or a series of arguments to determine the minimum in that series. You can try multiple things.
Use another variable to store a temporary minimum. Replace it every time you find a smaller odd value ( for every i in x... if the value is odd and is smaller than the previous odd value, replace it) and have it started with the first odd number you can find.
Take all the odd numbers and add them to another array on which you will apply the min function.
Hope this proves useful!
You could pass a generator into the min() function:
def min_odd(iterable):
return min(i for i in iterable if i % 2)
I didn't write i % 2 != 0 because any odd number will return 1 which has a Boolean value of True.
I added a parameter to the function that takes the iterable so it can be used for any iterable passed in.
min operates on an iterable. i is not an iterable in your code; it's the last element of the list.
You can achieve what you want with a filter, though:
min(filter(lambda e: e%2 != 0, x))

how to count function calling time within that function and the number can be restored in Python?

For example I have a function like this:
def a (x):
f(x)
if f(x) < 0:
a(x) # If a(x) is called over 30 times, then stop calling a(x) and return certain value.
else: return f(x)
I want to count the number of function calling under the if statement. Once the calling number is over certain number, then I can stop running a(x) and return certain values, and the calling number can be restored.
How can I do this? The regular counting wrapper is for the whole function, which is not suitable in this case I guess?
------------ Update -------------
Thanks to #Yevhen Kuzmovych now I have an example function like this:
def a (x, depth = 0):
b = x - 1
print(depth, b)
if b < 0:
if depth < 10:
a(b, depth + 1)
else:
return b
else:
return b
c = a(0) # this doesn't have a value
so with this function, c doesn't have a value. I don't understand. It seems the value is not returned.
You need to count depth of recursion:
def a(x, depth = 0):
f(x)
if f(x) < 0:
if depth < certain_number:
return a(x, depth + 1)
else:
return certain_value
else:
return f(x)
Recursion (Calling a function within a function) is useful sometimes, but in this case it is easy to avoid it and will probably be faster to do so. In Python, you can only go around 970 function calls before a RuntimeError: maximum recursion depth exceeded while ....
An iterative way to do this would be to just use a range in a for loop, where the times variable is the "calling number" (Or how many times the function has been called).
def a(x, retry=0):
for times in range(1, retry + 1): # xrange in Python 2
processed = f(x) # Store the value so you don't need to call f(x) again
if processed < 0:
continue # Try again, having gone through one more item in the range
return processed
return certain_value # You only get here if the range runs out

How to run down a list with recursion?

At first, I had to do it without recursion (just by looping which is pretty easy).
Now I have to do it with recursion, but I am not allowed to use any loop.
I guess I have to run down the list with recursion, but I don't quite understand what should be my base, or the reduction...
def long_strings_rec(strings, N):
'''
strings - a list of strings
N - an integer
Returns all strings in 'strings' of length bigger then 'N'
(This function is recursive and does not use loops)
'''
# Your code for question #2 (second function) starts here
# Your code for question #2 (second function) ends here
Any ideas? Can I have maybe an example of how to use recursion to take actions on lists indexes?
I used the helper function to do that, like #7stud suggested:
def helper (strings, K, results):
if len(strings) == 0:
return 0
elif len(strings[0]) > K:
results.append(strings[0])
strings.pop(0)
else:
strings.pop(0)
helper(strings, K, results)
return results
def long_strings_rec (strings, N):
'''
strings - a list of strings
N - an integer
Returns all strings in 'strings' of length bigger then 'N'
(This function is recursive and does not use loops)
'''
# Your code for question #2 (second function) starts here
return helper(strings, N, [])
# Your code for question #2 (second function) ends here
Worked like a charm. Hope it's not buggy.
Here's an example of how to use an accumulator:
def sum(nums):
return helper(nums, 0) #0 is the initial value for the accumulator
def helper(nums, total): #total is the accumulator
if len(nums) == 0:
return total
else:
num = nums.pop()
return helper(nums, total+num)
print sum([1, 2, 3])
--output:--
6
Basically, you redefine sum() so that it takes an additional accumulator parameter variable, then have sum() call the new function.
See if you can apply those principles to your problem.
As bjorn pointed out in the comments, you could do it like this too:
def mysum(nums, total=0):
if len(nums) == 0:
return total
else:
num = nums.pop()
return sum(nums, total+num)
print mysum([1, 2, 3])
--output:--
6

Categories

Resources