Having trouble understanding this recursion function - python

I was reviewing the topic of recursion in a tutorial site and came across the problem and solution below:
Problem:
Given an integer, create a function which returns the sum of all the individual digits in that integer. For example: if n = 4321, return 10 since 4+3+2+1=10.
Solution:
def sum_func(n):
if n<10:
return n
else:
return n%10 + sum_func(int(n/10))
pass
I understand the "if n<10" is the base case - if n is single digit, then just return n. What I couldn't wrap my head around is the "n%10 + sum_func(int(n/10))" line of code. Assume n is 235, n%10 will equal 5 and int(n/10) will equal 23. Then ultimately 5 + 23 will become 28 and not 10.
Could someone please help me understand what "n%10 + sum_func(int(n/10))" does? If you could walk through the logic one line at a time that would be greatly appreciated!

if n = 235 then int(n/10) is 23. However, you do not add 5 and 23. You add sum_func(int(n/10)) and 5.
sum_func(int(n/10)) is not int(n/10)
sum_func(int(n/10)) adds the digits in the number "23" together.
As such, sum_func(int(n/10)) == 2 + 3 == 5
sum_func(235) == sum_func(235)
== sum_func(23) + 5
== sum_func(2) + 3 + 5
== 2 + 3 + 5

As you say if there's only 1 digit return it.
The % is the modulus operator - i.e. the remainder when dividing by 10, or simply the last digit (i.e. 235%10 = 5)
int(n/10) drops the last digit since the int() function rounds down - i.e. 235 -> 23
Now what you seem to be confused by is within sum_func it calls sum_func again with the remainder once the last digit has been dropped i.e. 23 (this is the recursion part) which will then return 5.
i.e. you have
sum_func(235)
=5 + sum_func(23)
=5 + (3 + sum_func(2))
=5 + (3 + (2))
=10

Related

Is ther any other way to get sum 1 to 100 with recursion?

I'm studing recursive function and i faced question of
"Print sum of 1 to n with no 'for' or 'while' "
ex ) n = 10
answer =
55
n = 100
answer = 5050
so i coded
import sys
sys.setrecursionlimit(1000000)
sum = 0
def count(n):
global sum
sum += n
if n!=0:
count(n-1)
count(n = int(input()))
print(sum)
I know it's not good way to get right answer, but there was a solution
n=int(input())
def f(x) :
if x==1 :
return 1
else :
return ((x+1)//2)*((x+1)//2)+f(x//2)*2
print(f(n))
and it works super well , but i really don't know how can human think that logic and i have no idea how it works.
Can you guys explain how does it works?
Even if i'm looking that formula but i don't know why he(or she) used like that
And i wonder there is another solution too (I think it's reall important to me)
I'm really noob of python and code so i need you guys help, thank you for watching this
Here is a recursive solution.
def rsum(n):
if n == 1: # BASE CASE
return 1
else: # RECURSIVE CASE
return n + rsum(n-1)
You can also use range and sum to do so.
n = 100
sum_1_to_n = sum(range(n+1))
you can try this:
def f(n):
if n == 1:
return 1
return n + f(n - 1)
print(f(10))
this function basically goes from n to 1 and each time it adds the current n, in the end, it returns the sum of n + n - 1 + ... + 1
In order to get at a recursive solution, you have to (re)define your problems in terms of finding the answer based on the result of a smaller version of the same problem.
In this case you can think of the result sumUpTo(n) as adding n to the result of sumUpTo(n-1). In other words: sumUpTo(n) = n + sumUpTo(n-1).
This only leaves the problem of finding a value of n for which you know the answer without relying on your sumUpTo function. For example sumUpTo(0) = 0. That is called your base condition.
Translating this to Python code, you get:
def sumUpTo(n): return 0 if n==0 else n + sumUpTo(n-1)
Recursive solutions are often very elegant but require a different way of approaching problems. All recursive solutions can be converted to non-recursive (aka iterative) and are generally slower than their iterative counterpart.
The second solution is based on the formula ∑1..n = n*(n+1)/2. To understand this formula, take a number (let's say 7) and pair up the sequence up to that number in increasing order with the same sequence in decreasing order, then add up each pair:
1 2 3 4 5 6 7 = 28
7 6 5 4 3 2 1  = 28
-- -- -- -- -- -- -- --
8 8 8 8 8 8 8 = 56
Every pair will add up to n+1 (8 in this case) and you have n (7) of those pairs. If you add them all up you get n*(n+1) = 56 which correspond to adding the sequence twice. So the sum of the sequence is half of that total n*(n+1)/2 = 28.
The recursion in the second solution reduces the number of iterations but is a bit artificial as it serves only to compensate for the error introduced by propagating the integer division by 2 to each term instead of doing it on the result of n*(n+1). Obviously n//2 * (n+1)//2 isn't the same as n*(n+1)//2 since one of the terms will lose its remainder before the multiplication takes place. But given that the formula to obtain the result mathematically is part of the solution doing more than 1 iteration is pointless.
There are 2 ways to find the answer
1. Recursion
def sum(n):
if n == 1:
return 1
if n <= 0:
return 0
else:
return n + sum(n-1)
print(sum(100))
This is a simple recursion code snippet when you try to apply the recurrent function
F_n = n + F_(n-1) to find the answer
2. Formula
Let S = 1 + 2 + 3 + ... + n
Then let's do something like this
S = 1 + 2 + 3 + ... + n
S = n + (n - 1) + (n - 2) + ... + 1
Let's combine them and we get
2S = (n + 1) + (n + 1) + ... + (n + 1) - n times
From that you get
S = ((n + 1) * n) / 2
So for n = 100, you get
S = 101 * 100 / 2 = 5050
So in python, you will get something like
sum = lambda n: ( (n + 1) * n) / 2
print(sum(100))

10 digit number whose first n digits are divisible by n

So I came upon this little problem and I challenged myself to write my first program to solve it. The problem is to find a 10 digit number, for which if you take the first n digits, the resulting number must be divisible by n (eg. 1236, where 1 is divisible by 1, 12 by 2, 123 by 3 and 1236 by 4). My code is a little clumsy which i don't mind, but I'm getting error messages I don't understand.
from itertools import permutations
oddperm = permutations([1,3,7,9])
evenperm = permutations([2,4,6,8])
for odd in oddperm:
for even in evenperm:
num1 = (even[0]*(10**7)) + (even[1]*(10**5)) + (even[2]*10**3) + (even[3]*10)
num2 = (odd[0]*10**8 )+ (odd[1]*10**6) + (5*10**4) + (odd[2]*10**2) + (odd[3])
num = str((num1+num2)*10)
if (num[0]*10 + num[1]) % 2 == 0 and #etc etc etc and (num[0]*10**8 + num[1]*10**7 + num[2]*10**6 + num[3]*10**5 + 5*10**4 + num[5]*10**3 + num[6]*10**2 + num[7]*10 + num[8]) % 9 == 0:
print(num)
break
else:
continue
The trouble is im getting
TypeError Traceback (most recent call last)
<ipython-input-75-cb75172b012c> in <module>
10 num2 = (odd[0]*10**8 )+ (odd[1]*10**6) + (5*10**4) + (odd[2]*10**2) + (odd[3])
11 num = str((num1+num2)*10)
---> 12 if (num[0]*10 + num[1]) % 2 == 0 and ... and (num[0]*10**8 + num[1]*10**7 + num[2]*10**6 + num[3]*10**5 + 5*10**4 + num[5]*10**3 + num[6]*10**2 + num[7]*10 + num[8]) % 9 == 0:
13 print(num)
14 break
TypeError: not all arguments converted during string formatting
Also if someone has an idea on how to make that line a touch more elegant I'm all ears.
Thanks in advance for any and all contributions!
It looks to me like the error you describe is coming from a type conversion. You are converting num to a string, and then using indexing to get a certain digit of the number (which is fine), but before you can do any math with the digit, you need to convert it back into an int.
# num gets converted to a string
num = str((num1+num2)*10)
# num's digits get converted back into integers
if (int(num[0])*10 + int(num[1])) % 2 == 0:
print(num)
Additionally, to make your checking of each digit more elegant, you can use a for loop and check for failure rather than success. This is an interesting problem so I spent a bit of time on it, haha. The following function can be called in place of the long if (int(num[0])*10 + int(num[1])) % 2 == 0 and ... etc:, changing it to simply if check_num(num):.
def check_num(num:str):
# define powers in advance for convenience
powers = [10**p for p in range(len(num))]
# check that the number satisfies the desired property
place = 1
while place < len(num):
sum = 0
# check each digit
for i in range(place+1):
sum += int(num[i]) * powers[place - i]
# check for failure
if sum % (place+1) != 0:
return False
# check the next place
place += 1
# we made it all the way through
return True
Hope this is enlightening.

How to determine the range to calculate the last digit of the sum of Fibonacci numbers using Pisano Period?

I already solved this problem. If I understood correctly the logic is the following: since we need the last digit of a sum of Fibonacci numbers we can use:
𝐹n mod 10 == (𝐹n % Pisano 10) mod 10
My issue is with the range of the sum. I don't know how to find it. Since Pisano 10 = 60, the last digits repeat with a period of 60 so I don't need to calculate the Fibonacci values from 0 to N but I don't know how to determine this range.
I found solutions for this problem but I never understood how they found their range. For example:
Original here
def sum_fib_last(n):
if(n <= 1):
return n
previous = 0
current = 1
rem = n % 60 #60 is Pisano period of 10
for i in range(2, rem + 3):
previous, current = current, (previous + current) % 60
return(current-1) % 10
I don't know why the range is from (2 to rem+3) and why we return the Fibo value minus 1. Similar solution
This solution uses a different range:
def last_digit(n):
a, b = 0, 1
for i in range((n + 2) % 60):
a, b = b, (a + b) % 10
return 9 if a == 0 else a - 1
I need help to understand how these ranges where determined, I don't understand the logic behind them.
They should have been a little bit clearer. The sum of the first n Fibonacci numbers is Fib(n + 2) - 1. This is easy to prove by induction.

binary to decimal using recursion,python

Need help converting binary to decimal, using recursion.
So far I have :
(2* int(s[0])) + int(s[1])
with base cases for when s==0 and s==1.
I'm not sure how to pass this recursively so that the function will pass through all 1's and 0's in input,s.
The basic idea is to pick off the last character of the string and convert that to a number, then multiply it by the appropriate power of 2. I've commented the code for you.
# we need to keep track of the current string,
# the power of two, and the total (decimal)
def placeToInt (str, pow, total):
# if the length of the string is one,
# we won't call the function anymore
if (len(str) == 1):
# return the number, 0 or 1, in the string
# times 2 raised to the current power,
# plus the already accumulated total
return int(str) * (2 ** pow) + total
else:
# grab the last digit, a 0 or 1
num = int(str[-1:])
# the representation in binary is 2 raised to the given power,
# times the number (0 or 1)
# add this to the total
total += (num * (2 ** pow))
# return, since the string has more digits
return placeToInt(str[:-1], pow + 1, total)
# test case
# appropriately returns 21
print(placeToInt("10101", 0, 0))
Now, let's go through it manually, so you understand why this works.
# n = 101 (in binary
# this can also be represented as 1*(2^2) + 0*(2^1) + 1*(2^0)
# alternatively, since there are three digits in this binary number
# 1*(2^(n-1)) + 0*(2^(n-2)) + 1*(2^(n-3))
So what does this mean? Well, the rightmost digit is 1 or 0 times 2 raised to the power of zero. In other words, it either adds 1 or 0 to the total. What about the second rightmost digit? It either adds 0 or 2 to the total. The next one? 0 or 4. See the pattern?
Let's write the pseudocode:
let n = input, in binary
total = 0
power of 2 = 0
while n has a length:
lastDigit = last digit of n
add (2^pow)*lastDigit to the current total
Since we start with a power and a total of 0, you can see why this works.
def IntegerConvert(num, base):
if num == 0:
return 0
else:
IntegerConvert.sum += pow(10, IntegerConvert.counter)*(num % base)
IntegerConvert.counter += 1
IntegerConvert(num/base, base)
return IntegerConvert.sum
IntegerConvert.counter = 0
IntegerConvert.sum = 0
print IntegerConvert(10, 2)

Digital sum, Python

I need to write a code that counts the sum of the digits of a number, these is the exact text of the problem:The digital sum of a number n is the sum of its digits. Write a recursive function digitalSum(n) that takes a positive integer n and returns its digital sum. For example, digitalSum(2019) should return 12 because 2+0+1+9=12. These is the code I wrote :
def digitalSum(n):
L=[]
if n < 10:
return n
else:
S=str(n)
for i in S:
L.append(int(i))
return sum(L)
These code works fine, but it's not a recursive function, and I'm not allowed to change any int to str. May you help me?
Try this:
def digitalSum(n):
if n < 10 :
return n
return n % 10 + digitalSum( n // 10 )
Edit: The logic behind this algorithm is that for every call of the recursive function, we chop off the number's last digit and add it to the sum. First we obtain the last digit with n % 10 and then we call the function again, passing the number with the last digit truncated: n // 10. We only stop when we reach a one-digit number. After we stop, the sum of the digits is computed in reverse order, as the recursive calls return.
Example for the number 12345 :
5 + digitalSum( 1234 )
5 + 4 + digitalSum( 123 )
5 + 4 + 3 + digitalSum( 12 )
5 + 4 + 3 + 2 + 1 <- done recursing
5 + 4 + 3 + 3
5 + 4 + 6
5 + 10
15
It's homework, so I'm not writing much code. Recursion can be used in the following way:
get the first (or last) digit
format the rest as a shorter number
add the digit and the digital sum of the shorter number (recursion!)
This is more of a question related to algorithms.
Here is your answer:
def digit_sum(a):
if a == 0:
return 0
return a % 10 + digit_sum(a/10)
Let me know if you don't understand why it works and I'll provide an explanation.
Some hints:
You can define inner functions in Python
You can use the modulus operator (look up its syntax and usage) to good effect, here
There's no need to build up an explicit list representation with a proper recursive solution
EDIT The above is a bit "bad" as a general answer, what if someone else has this problem in a non-homework context? Then Stack Overflow fails ...
So, here's how I would implement it, and you need to decide whether or not you should continue reading. :)
def digitalSum(n):
def process(n, sum):
if n < 10:
return sum + n
return process(n / 10, sum + n % 10)
return process(n, 0)
This might be a bit too much, but even in a learning situation having access to one answer can be instructive.
My solution is more a verbose than some, but it's also more friendly towards a tail call optimizing compiler, which I think is a feature.
def digital_sum(number):
if number < 10:
return number
else:
return number % 10 + digital_sum(number / 10)
def sumofdigits(a):
a = str(a)
a = list(a)
b = []
for i in a:
b.append(int(i))
b = sum(b)
if b > 9:
return sumofdigits(b)
else:
return b
print sumofdigits(5487123456789087654)
For people looking non-recursive ways,
Solution 1:
Using formula,
digits = int(input())
res = (digits * (digits + 1) // 2)
Solution 2:
Using basic syntax
numbers = [6, 5, 3, 8, 4, 2, 5, 4, 11]
total = numbers[0]
print(f'{total}')
for val in numbers[1:]:
print(f'{total} + {val} = {total + val}')
total += val
gives
6
6 + 5 = 11
11 + 3 = 14
14 + 8 = 22
22 + 4 = 26
26 + 2 = 28
28 + 5 = 33
33 + 4 = 37
37 + 11 = 48
Still you can do it in O(log10 n)...cancel out all the digits that adds to 9 then if no numbers left,9 is the answer else sum up all the left out digits...
def rec_sum_Reduce(n) :
ans = 0
for i in map(int,str(n)) :
ans = 1+(ans+i-1)%9
return ans
def drs_f(p):
drs = sum([int (q) for q in str(p)])
while drs >= 10:
drs = sum([int(q) for q in str(drs)])
return drs
def digitalSum(n):
if n < 10:
return n
else:
return ???
The 1st part is from your existing code.
The ??? is the part you need to work out. It could take one digit off n and add it to the digitalSum of the remaining digits.
You don't really need the else, but I left it there so the code structure looks the same

Categories