Adding the digits of an int and Python - python

import sys
def keepsumming(number):
numberlist = []
for digit in str(number):
numberlist.append(int(digit))
total = reduce(add, numberlist)
if total > 9:
keepsumming(total)
if total <= 9:
return total
def add(x,y):
return x+y
keepsumming(sys.argv[1])
I want to create a function that adds the individual digits of any number, and to keep summing digits until the result is only one digit. (e.g. 1048576 = 1+0+4+8+5+7+6 = 31 = 3+1 = 4). The function seems to work in some laces but not in others. for example:
$python csp39.py 29
returns None, but:
$python csp39.py 30
returns 3, as it should...
Any help would be appreciated!

As others have mentioned, the problem seems to be with the part
if total > 9:
keepsumming(total) # you need return here!
Just for completeness, I want to present you some examples how this task could be solved a bit more elegantly (if you are interested). The first also uses strings:
while number >= 10:
number = sum(int(c) for c in str(number))
The second uses modulo so that no string operations are needed at all (which should be quite a lot faster):
while number >= 10:
total = 0
while number:
number, digit = divmod(number, 10)
total += digit
number = total
You can also use an iterator if you want to do different things with the digits:
def digits(number, base = 10):
while number:
yield number % base
number //= base
number = 12345
# sum digits
print sum(digits(number))
# multiply digits
from operator import mul
print reduce(mul, digits(number), 1)
This last one is very nice and idiomatic Python, IMHO. You can use it to implement your original function:
def keepsumming(number, base = 10):
if number < base:
return number
return keepsumming(sum(digits(number, base)), base)
Or iteratively:
def keepsumming(number, base = 10):
while number >= base:
number = sum(digits(number, base))
UPDATE: Thanks to Karl Knechtel for the hint that this actually is a very trivial problem. It can be solved in one line if the underlying mathematics are exploited properly:
def keepsumming(number, base = 10):
return 1 + (number - 1) % (b - 1)

There's a very simple solution:
while number >= 10:
number = sum(divmod(number, 10))

I am fairly sure you need to change
if total > 9:
keepsumming(total)
into
if total > 9:
return keepsumming(total)
As with most recursive algorithms, you need to pass results down through returning the next call.

and what about simply converting to string and summing?
res = 1234567
while len(str(res)) > 1 :
res = sum(int(val) for val in str(res))
return res
Thats's what I use to do :)

Here is a clean tail-recursive example with code that is designed to be easy to understand:
def keepsumming(n):
'Recursively sum digits until a single digit remains: 881 -> 17 -> 8'
return n if n < 10 else keepsumming(sum(map(int, str(n))))

Here you go:
>>> sumdig = (lambda recurse: (lambda fix: fix(lambda n: sum(int(c) for c in str(n)))) (recurse(lambda f, g: (lambda x: (lambda d, lg: d if d == lg else f(f,g)(d))(g(x),x)))))(lambda f: lambda x: f(f,x))
>>> sumdig(889977)
3
You are sure to get full, if not extra, credit for this solution.

Your code as currently written need to replace the recursive call to keepsumming(total) with return keepsumming(total); python does not automatically return the value of the last evaluated statement.
However, you should note that your code has redundancies.
for digit in str(number):
numberlist.append(int(digit))
total = reduce(add, numberlist)
should become
from operator import add
total = reduce(add, (int(digit) for digit in str(number)))

A code golf-able version that doesn't require a while loop, or recursion.
>>> import math
>>> (lambda x: sum(int((x * 10 ** -p) % 10) for p in range(math.ceil(math.log(x, 10)))))(1048576)
31
This is probably what I'd use though.
def sum_digits(number):
return sum(
int(number * (10 ** -place) % 10)
for place in range(math.ceil(math.log(number, 10)))
)
It's easier to see what's going on if you append to a list instead of summing the integer values.
def show_digits(number):
magnitude = int(math.log(number, 10))
forms = []
for digit_place in range(magnitude + 1):
form = number * (10 ** -digit_place) # force to one's place
forms.append(form)
return forms
>>> show_digits(1048576)
[1048576, 104857.6, 10485.76, 1048.576, 104.8576, 10.48576, 1.048576]

For keepsumming that takes a string:
def keepsumming(number):
return number if len(number) < 2 \
else keepsumming(str(sum(int(c) for c in number)))
For keepsumming that takes a number:
def keepsumming(number):
return number if number < 10 \
else keepsumming(sum(int(c) for c in str(number)))

Related

Reversing an integer using recursion in Python

While practicing recursion I came across a question to reverse an integer using recursion. I tried to do the question without converting the integer into a string.
I was able to solve the question partially but the output would always come without any of the zeroes from the original input. Below is the code I came up with:
def reverseNumber(n):
if (n//10) == 0:
return n
lastDigit = n%10
ans = reverseNumber(n//10)
nod = 0
for i in str(ans):
nod += 1
return (10**nod)*lastDigit + ans
Upon inspection I could see that this was happening because when lastDigit is 0 it only returned the reversed integer from the recursive call i.e input 4230 will give 324.
But this also meant that all zeroes between the original input would also get removed as we went deeper in the recursive calls.
So please tell me how to modify this code so that zeroes in the original input are not removed while reversing.
You probably need just this:
def rev(n):
if n>0:
return str(n%10)+rev(n//10)
else:
return ''
reverseNumber should return an int and accept positive and negative numbers.
The simplest way to fix your code, without handling negative numbers, is:
def reverseNumber(n):
if n == 0:
return 0
lastDigit = n%10
n //= 10
return int(str(lastDigit) + str(reverseNumber(n))) if n else lastDigit
for test in (0, 123, 120):
print(test, reverseNumber(test))
Prints:
0 0
123 321
120 21
Yes! The reverse of 120 is 21 when you are dealing with int types as opposed to str types.
Another implementation that does handle negative numbers takes a whole different approach:
I have broken this out into two functions. Function rev is a generator function that assumes that it is being called with a positive, non-negative number and will recursively yield successive digits of the number in reverse. reverseNumber will join these numbers, convert to an int, adjust the sign and return the final result.
def reverseNumber(n):
def rev(n):
assert n >= 0
yield str(n % 10)
n //= 10
if n != 0:
yield from rev(n)
if n == 0: return 0 # special case
x = int(''.join(rev(abs(n))))
return x if n >= 0 else -x
tests = [0, 132, -132, 120]
for test in tests:
print(test, reverseNumber(test))
Prints:
0 0
132 231
-132 -231
120 21
For all non-negative n, when n < 10 it is a single digit and already the same as its reverse -
def reverse(n = 0):
if n < 10:
return str(n)
else
return str(n%10) + rev(n//10)
you can also try the following Python3 code. It will cover positive and negative integers to be reversed as integers - not as strings ...
x = int(input("What integer shall be reversed? "))
n = abs(x) # ... to handle negative integers
r = 0 # ... will hold the reversed int.
while n > 0: # Recursion part reversing int.
r = (r * 10) + (n % 10) # using '%' modulo
n = int(n / 10) # and a 'dirty way' to floor
if x < 0: # Turn result neg. if x was neg.
return (r * -1)
else:
return r # Keep result pos. if x was pos.
This approach will leave your zeros in the middle of the integer intact, though it will make any zero at the end of the initial number vanish - rightfully so as integers do not start with a zero. ;))

product of digits as a single-digit number

I am trying to compute the product of non-zero digits,
until the result is a single-digit number. For example, the number 512983 is 2, because 5×1×2×9×8×3 = 2160 and 2×1×6 = 12 (note the omission of the zero digit) and 1 × 2 = 2. But every time I run this I only get 0
def prod_digits(n):
a = 1
for each in str(n):
a = a * int(each)
return a
prod_digits(123)
Try this:
def prod_digits(n):
a = 1
for each in str(n):
if each is not '0':
a = a * int(each)
return a
a = 123
while (a > 10):
a = prod_digits(a)
print a
There are multiple issues with your code
Since initial value of a is 0, any subsequent multiplications will give 0. Change it to 1.
Your function needs to be called recursively until the argument to function is a single digit.
You need to ignore 0 while multiplying digits.
Or you can use the reduce function from functools:
from functools import reduce
def compute_nz_product(n):
digits = [int(c) for c in str(n) if c is not '0']
result = reduce(lambda x, y: x*y, digits)
if result < 10:
return result
else:
return compute_nz_product(result)
print(compute_nz_product(512983))
Output:
2

Digital Root without loops Python

def digit_sum(n):
'''(int)->number
Returns the sum of all the digits in the given integer, n'''
if n<10:
return n
return n%10 + digit_sum(n//10)
def digital_root(n):
'''(int)->number
Returns the resulting sum of the digits in the given integer until it reaches a single digit number; via digit_sum'''
while n>9:
n=sum(digit_sum(n))
return n
Wrote the code for digit_sum and then used recursion to write digital_root. How would I go about this? Any help is appreciated!
Wikipedia lists a simple O(1) formula for the digital root:
def digit_root(n):
return (n - 1) % 9 + 1
This does not take into account an input less than 1, so you can modify as follows, with the assumption that the input is a whole number:
def digit_root(n):
return (n - 1) % 9 + 1 if n else 0
Examples:
>>> digit_root(1)
1
>>> digit_root(11)
2
>>> digit_root(235)
1
So the idea is that you have to use recursion for the last one as well? In that case, this should do the job:
def digital_root(n):
if n < 10:
return n
return digital_root(digit_sum(n))
Try this:
def num(n) :
sum = 0 #provided sum as 0
for i in str(n):
a = int(n) % 10 #taken variable a
sum = sum + a #put the sum.
n = n/10
print(sum)
if sum < 10:
print(str(sum) + "=this is a digital root")
else:
num(sum)
please try the following code:
def dgtl_rt(n):
return n%9 or n and 9
print(dgtl_rt(123))
def droot(a):
while a>=10:
b =int(a/10) #other digit(s)
c =a-(b*10) #the rightmost digit
a =b+c #add together
return a
I have not seen this solution anywhere, so I thought it would be nice to share, i discovered it myself! Just 1 looping structure.
{def MDR(n):
'''
this function returns multiplicative digital root.
'''
count, mdr = 0, n
while mdr > 9:
m, digitsMul = mdr, 1
while m:
m, md = divmod(m, 10)
digitsMul *= md
mdr = digitsMul
count += 1
return count, mdr}

RECURSIVE function that will sum digits of input

Trying to write a piece of code that will sum the digits of a number. Also I should add that I want the program to keep summing the digits until the sum is only 1 digit.
For example, if you start with 1969, it should first add 1+9+6+9 to get 25. Since the value 25 has more than a single digit, it should repeat the operation to obtain 7 as a final answer.
Was just wondering how I could pull this off and possibly make it recursive as well. This is what I have so far
def sum_digits3(n):
r = 0
while n:
r, n = r + n % 10, n // 10
return r
Convert back and forth between strings and ints, make use of sum().
>>> def foo(n):
n = str(n)
if len(n) == 1:
return int(n)
return foo(sum(int(c) for c in n))
>>> foo(1969)
7
>>>
def foo(n):
n = str(n)
if len(n) == 1:
return int(n)
return foo(sum(int(c) for c in n))
It is as simple as involving explicitly the recursion.
def sum_digits3(n):
r = 0
while n:
r, n = r + n % 10, n // 10
if len(str(r))>1:
return sum_digits3(r)
return r
But i must admit that i am going to read the links given by suspicious dog. And the answer of wwii is smarter than mine.

Designing a recursive function that uses digit_sum to calculate sum of digits

def digit_sum(n):
if n==0 or n==1:
return n
else:
return n+digit_sum(n-1)
def digital_root(n):
if n<10:
return n
else:
return digit_sum((n // 10) + n % 10)
I am trying to use digit_sum to calculate the sum of digits of digital_root can someone help me please. I am trying to use a recursive function for digital_root.
Running the file in Python shell:
digital_root(1969)
This should calculate 1+9+6+9=25 then since 25 is greater than 10 it should then calculate the sum of its digits 2+5 so that the final answer is 7.
To get the last digit of a (positive integer) number you can calculate the modulo:
last_digit = n % 10
The remainder of the number (excluding the last place) is:
rest = (n - last_digit) / 10
This should in theory be enough to split a number and add the digits:
def sum_digits(n):
if n < 10:
return n
else:
last_digit = n % 10
rest = n // 10
# or using divmod (thanks #warvariuc):
# rest, last_digit = divmod(n, 10)
return last_digit + sum_digits(rest)
sum_digits(1969) # 25
If you want to apply this recursivly until you have a value smaller than 10 you just need to call this function as long as that condition is not fulfilled:
def sum_sum_digit(n):
sum_ = sum_digit(n)
if sum_ < 10:
return sum_
else:
return sum_sum_digit(sum_)
sum_sum_digit(1969) # 7
Just if you're interested another way to calculate the sum of the digits is by converting the number to a string and then adding each character of the string:
def sum_digit(n):
return sum(map(int, str(n)))
# or as generator expression:
# return sum(int(digit) for digit in str(n))
If you really require a recursive solution without using any loops (for, while) then you can always recurse again to ensure a single digit:
def digital_root(n):
if n < 10:
return n
a, b = divmod(n, 10)
b += digital_root(a)
return digital_root(b)
>>> digital_root(1969)
7
Or you could just not recurse at all:
def digital_root(n): # n > 0
return 1+(n-1)%9
>>> digital_root(1969)
7
try this...
digitSum = 0
solution = 0
S = raw_input()
S = list(map(int, S.split()))
#print S
for i in S:
digitSum += i
#print digitSum
singleDigit = len(str(digitSum)) == 1
if singleDigit == True: solution = digitSum
while singleDigit == False:
solution = sum( [ int(str(digitSum)[i]) for i in range( 0, len(str(digitSum))) ] )
digitSum = solution
singleDigit = len(str(solution)) == 1
print(solution)

Categories

Resources