Summing the elements of a list recursively - python

def sum(L):
if len(L) == 1:
return L[0]
i = sum (len (L) // 2)
if len(L) > 1:
return i + i
L=[2,4]
print (sum(L))
when i try to run it there is a TypeError: object of type 'int' has no len().

In sum (len (L) // 2), you're passing an integer (the result of len(L) // 2) as the L argument to your sum() function. (Please don't give functions the same name as built-in functions.) The recursively-called sum() then tries to evaluate len(L) == 1 on this integer, but integers don't support len(), and so you get the error message in question. What exactly are you actually trying to do?

I think what you were aiming for was to write a recursive sum function that continuously splits the list into smaller chunks. So basically what you need to do is compute the index of the midpoint, then use list slicing to pass the first sublist and second sublist recursively back into the function, until hitting your base case(s) of 0 or 1 elements remaining.
def add(values):
if len(values) == 0:
return 0
elif len(values) == 1:
return values[0]
mid = len(values)//2
return add(values[:mid]) + add(values[mid:])
>>> add([1,2,3,4,5])
15

Don't name your function sum, it shadows the builtin function
Implement your function so as to clearly define a base case and a recursive case.
For the base case, when the length is 1, return that element. You've got this right.
For the recursive case, split your list into half and recursively compute the sum for each half.
def sum_recursive(L):
if len(L) == 1:
return L[0]
idx = len(L) // 2
return sum_recursive(L[:idx]) + sum_recursive(L[idx:])
sum_recursive must always receive a list and return an integer.
Some dry runs:
In [5]: sum_recursive([1, 2, 4, 8])
Out[5]: 15
In [6]: sum_recursive([2, 4])
Out[6]: 6
Keep in mind that this won't be able to handle empty lists as input. If you want to account for that as well, change your base case to:
def sum_recursive(L):
if len(L) <= 1:
return sum(L)
...
We're making use of the builtin sum function here which handles empty lists gracefully by returning 0. For single-element lists, the first element is returned (this is also why it is important you don't shadow these utility functions).
If you don't want to use sum there, you'll need to split your base case into two parts:
def sum_recursive(L):
if len(L) == 0:
return 0
elif len(L) == 1:
return L[0]
...

In your code
i = sum (len (L) // 2)
line is throwing an error because in recursion after the first call of sum() you are passing an integer not list
def sum(L):
if len(L) == 0:
return 0
elif len(L) == 1:
return L[0]
else:
index = len(L)-1
return L[index] + sum(L[0:index])
L=[2,4]
print (sum(L))

Related

Adding two sum with recursion

Question: Given an array of integers nums and an integer target, return indices of the two numbers such that they add up to target.Each input would have exactly one solution, and you may not use the same element twice. for example.
Input: nums = [2,7,11,15], target = 9
Output: [0,1]
Output: Because nums[0] + nums[1] == 9, we return [0, 1].
I'm trying one make a helper function that add the first number with each of the rest number, and run this helper function recursively on the give list nums. I'm not sure where my codes is wrong. (I know there are other more efficient algorithms, for the purpose of exercise pls stick to this approach)
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
# One function that takes a list, and find out first + i ==target, if exists
def help_(lst,tar):
for i, n in enumerate(lst[1:],start=1):
if lst[0]+n ==tar:
return i
else:
return False
ctn=0
#base case, if a sublist whose first num + another another is target
if help_(nums,target) != False:
return [0+ctn,help_(nums,target)+ctn] # return two indices from helper, adding the time it looped
else:
ctn =+1
return help_(nums[1:],target)
There are a few issues:
Your recursive call return help_(nums[1:],target) will not return a pair, but one index (or False), so this should never be returned in the main function. Instead make the recursive call on twoSum, which will return a pair (if successful). Then you will still need to add 1 to both indices before returning that.
The helper function is returning always in the first iteration of the loop. You should move the return False out of the loop's body.
It is a pity that you call the helper function twice with the same arguments. Just store the result in a temporary variable to avoid re-executing it
Here is your code with those corrections:
class Solution:
def twoSum(self, nums, target):
# One function that takes a list, and find out first + i ==target, if exists
def help_(lst,tar):
for i, n in enumerate(lst[1:],start=1):
if lst[0]+n ==tar:
return i
return False
ctn=0
res = help_(nums,target)
if res != False:
return [0+ctn, res+ctn]
else:
ctn =+1
x, y = self.twoSum(nums[1:], target)
return x+1, y+1
As you noted in your question this is not the most efficient way to solve this problem.
Using a dictionary leads to a better time complexity. In case you cannot find it, here is such a solution (spoiler):
d = { target - num: i for i, num in enumerate(nums)}`
return next((i, d[j]) for i, j in enumerate(nums) if j in d.keys() and i != d[j])
Your approach is globally valid (the implementation is not) but you have to keep track of a lot of parameters
The ideal is to only check the combinations:
nums = [2,7,11,15]
s = 9
from itertools import combinations
for (i,a),(j,b) in combinations(enumerate(nums), r=2):
if a+b == s:
print(i,j)
Output: 0 1
NB. I purposely proposed an answer with a module to give you the chance to rewrite it with a classical loop
for i in range(len(nums) - 1):
for j in range(i + 1, len(nums)):
total = nums[i] + nums[j]:
if total == target:
return nums[i], nums[j]

Recursive function return tuples of even index values?

Is it possible to return tuples of only even indexes through recursion?
This is what I came up with it so far.
def even(tup):
if not tup:
return ()
if tup.index(tup[0])+1 % 2 == 0:
return tuple(tup[0]) + even(tup[1:])
Passed argument gonna be look like this:
('c','b','z','e','m','f','j')
And my desired result would be:
First element in the tuple count as 1 = 'c', so for the even numbers it would return b, e, and f instead.
('b','e','f')
There are some requirements that I cannot mutate or re assigning the parameter at all.
What's the best way to approach this recursion?
I can solve this if it was list of numbers, but having a problem with this one.
I was able to come up with this recursive strategy. A noob strategy, I guess. :P
a = ('c','b','z','e','m','f','j')
def recFunc(a, theIndex):
if theIndex%2 == 1:
if theIndex < len(a):
value = recFunc(a, theIndex+1)
return (a[theIndex], ) + value
else:
return ()
else:
return (recFunc(a, theIndex+1))
print(recFunc(a, 0))
It seems to be self-explanatory. :)
Note: Maximum depth reaches at ~1000 elements.
EDIT: If you cannot add any other parameter and change it, how about such a solution (inspired from your work)?
def recFunc(a):
if len(a) == 0 or len(a) == 1:
return ()
# print(a)
return (a[1],) + recFunc(a[2:])
Don't you want just something like this?
tup = tuple(item for i, item in enumerate(tup) if i % 2 == 1)
Recursive function is unnecessary here. If you want to operate with tuple() items I would recommend you to cast it to list().
Also I'm not sure what you are trying to achieve here:
if tup.index(tup[0])+1 % 2 == 0:
tup[0] returns first element
tup.index(tup[0]) returns index of first element => 0
then 0+1 % 2 == 0 is always False
Edit:
But recursive function that returns tuple of "even" index values could look like this:
def even(tup):
if len(tup) <= 1:
return
elif len(tup) <= 3:
return tup[1]
return (tup[1], *even(tup[2:]))

Python Recursion List Sum of Pairs

I am supposed to write two functions that do the exact same thing but their implementation is different.
The function takes as input a list of positive integers and a positive integer n, and returns True if two of the numbers in list equal to n. Otherwise, it returns False.
The first function is supposed to use a nested a loop, which I was able to get.
The second functions is not supposed to use a nested loop. However, you are supposed to sort the list out and then solve the problem.
Here is what I have for the second function.
def pairs2(lst, n):
lst.sort()
if len(lst) == 2:
if lst[0] + lst[1] == n:
return True
else:
return False
elif len(lst) >= 3:
for i in range(len(lst) - 1):
if lst[0] + lst[i + 1] == n:
return True
lst.remove(lst[0])
pairs2(lst, n)
The function works until the last two lines are implemented. After that, it doesn't return anything. What is wrong with my function?
Also, are they any other alternatives to that I do not use recursion? I just came up with using recursion since it was the first idea that I got.
A recursive algorithm that eliminates the largest number at each recursive step:
def pairs2(lst, n, s=False):
if len(lst) < 2: return False
if not s: lst = sorted(lst)
for item in lst:
if item + lst[-1] > n:
return pairs2(lst[:-1], n, True)
if item + lst[-1] == n:
print item, lst[-1]
return True
return False
The s parameter indicates whether the list is already sorted or not.
def pairs2(lst, n):
[pair for pair in itertools.combinations(lst,2) if sum(pair) == n]
Instead of using recursion, you could use the brute-force approach to find the pairs using the itertools.combinations.
Read more about itertools: https://docs.python.org/2/library/itertools.html

Recursion depth error in simple Python program

I am new to programming, and was trying to solve this problem on Project Euler using basic Python.
Essentially, I tried to use recursion based on the largest value chosen at every stage, and using a list to maintain possible options for future choices.
The code is short and is given below:
def func(n,l):
if n<0:
return 0
if l==[1] or n==0:
return 1
else:
j=0
while l != []:
j=j+func(n-l[0],l)
del l[0]
return j
print func(200,[200,100,50,20,10,5,2,1])
For instance, if we have
func(5,[5,2,1])
the recursion splits it into
func(0,[5,2,1]) + func(3,[2,1]) + func(4,[1])
But the code never seems to go through. Either it says that there is a list-index-out-of-range error, or a maximum-recursion-depth error (even for very small toy instances). I am unable to find the mistake. Any help will be much appreciated.
In Python lists are passed into functions by reference, but not by value. The simplest fix for your program is changing recursive call to func(n - l[0], l[:]). In this way list will be passed by value.
One thing you're failing to take into account is that the following:
j=j+func(n-l[0],l)
doesn't make a copy of l.
Therefore all recursive invocations of func operate on the same list. When the innermost invocation deletes the last element of l and returns, its caller will attempt to del l[0] and will get an IndexError.
At each recursion, make the following 2 decisions:
Take the first coin (say f) from available coin types, then check if we can made (n-f) from those coins. This results in a sub-problem func(n - f, l)
Ignore the first coin type, and check if we can make n from the remaining coin types. This results in a sub-problem func(n, l[1:])
The total number of combinations should be the sum of the two sub-problems. So the code goes:
def func(n, l):
if n == 0:
return 1
if n < 0 or len(l) == 0:
return 0
if l == [1] or n == 0:
return 1
return func(n - l[0], l) + func(n, l[1:])
Each recursion a copy of l is made by l[1:]. This can be omitted by pop element before next recursion and restore with append afterwards.
def func(n, l):
if n == 0:
return 1
if n < 0 or len(l) == 0:
return 0
if l == [1] or n == 0:
return 1
full = func(n - l[-1], l)
last = l.pop()
partial = func(n, l)
l.append(last)
return full + partial

How to rewrite this function as a recursive function?

def digits(n):
res = []
while n > 0:
res.append(n % 10)
n /= 10
return res
I want to rewrite this function so it uses recursion. I'm currently lost as to what to do. Can anyone give me some direction?
To create a recursive function you need to determine two things:
1) The base case - the condition on which you want to stop recursion
2) The general case - what to do on every input but the base case
You have already found both of these things, the base case is the while loop condition and the general case is the inside of the while loop. Try to use this information to move forward.
Here's a possible solution:
def digits(n):
if n < 10:
return [n]
return digits(n/10) + [n%10]
digits(123)
> [1, 2, 3]
The above solution fixes a bug in your code, you were returning the digits in reverse order. Also notice that n must be an integer greater than or equal to zero for producing correct results.
Here's how it works:
If the number is less than 10, then return a list with the number, as there are no more digits to be processed
If the number is greater than 9, get the last digit in the current number and add it to the end of the list that results of recursively calling digits on a smaller number - namely, the number without the last digit that we just processed.
The call to digits(123) will look like this at each step of the recursion:
digits(123) = digits(123/10) + [3]
digits(12) = digits(12/10) + [2]
digits(1) = [1]
Now we go up the call stack:
[1]
[1] + [2]
[1, 2] + [3]
[1, 2, 3]
EDIT :
Accepting #thg435's challenge, here's a tail-recursive solution:
def digits(n):
def loop(i, acc):
if i < 10:
return [i] + acc
return loop(i/10, [i%10] + acc)
return loop(n, [])
When you use recursion, a good basis is to have two cases to check, a base case and a recursive case. The base case is the conditions and result under which the program returns, in your case, the base case would be when n > 0 (If you think of it like a while loop, it's the condition for the while loop exiting). The recursive case (there can be multiple of these) occur when the loop isn't done, if you compare to a while loop, this is basically the body of the loop. At the end of the recursive case, you need to call the function again with your changes to the input, in this case n/10.
So, your function definition would be something like:
def digits(n):
For the base case, you want to check if n is 0, and, if it is, return the empty list:
if n <= 0:
return []
Now, in the recursive case, you want to append n%10 to the list and call your function again, only you want to call it with a different n, changed as you had it in your while loop:
else:
return [n%10]+digits(n/10)
So, if you trace this through, for every recursive case, you get a list containing n%10, then it adds the result of the new call, which will be either (n/10)%10 or the empty list. For example, running this function with n=100 would break down like this:
newlist = digits(100)
newlist = [100%10]+digits(100/10)
newlist = [100%10]+([10%10] + digits(10/10))
newlist = [100%10]+([10%10] + ([1%10] + digits(10/10)))
newlist = [100%10]+([10%10] + ([1%10] + ([])))
newlist = [0,0,1]
Nested parens are used to show how the function digits gets rewritten inline.
def digits(n):
res = []
res.append(n%10)
n /= 10
if n != 0:
return res + digits(n)
else:
return res

Categories

Resources