简体   繁体   中英

recursive sum of all the digits in a number

I am stuck in this exercise.

Task:

A digital root is the recursive sum of all the digits in a number. Given n, take the sum of the digits of n. If that value has more than one digit, continue reducing in this way until a single-digit number is produced. This is only applicable to the natural numbers.

Here's how it works:

digital_root(16)
1 + 6 = 7

digital_root(942)
9 + 4 + 2 = 15... 1 + 5 =6

My approach is here. Any tips on how to properly return correct value? I would appreciate any help.

def digital_root(n):
    answ = 0
    s = 0
    x = str(n)

    for i in range(0, len(x)):
        s = s + int(x[i])
    if len(str(s)) > 1:
        digital_root(s)
    elif len(str(s)) == 1:
        answ = s # here is an answer
        return answ # answer is 2 but this one is not returning 2, why?

    return answ # here it returns answ=0, I want to return 2...

print(digital_root(493193))

What do you say about this:

def digital_root(n):
    if n<10 :
         return n
    return digital_root( n%10 + digital_root( n//10 ) )

The main problem is that, when doing the recursive calls, you're not assigning the return value to anything, so you'll always get 0 for any value that requires more than one pass.

Also, after the recursive call, the length should be 1 so the following elif is not necessary and will cause incorrect return values since it won't be assigning s to answ

Fixed version:

def digital_root(n):
    answ = 0
    s = 0
    x = str(n)
    for i in range(0, len(x)):
        s = s + int(x[i])
    if len(str(s)) > 1:
       s = digital_root(s)
    answ = s # You could even return s directly
    return answ

print(digital_root(493193))

Here is my take on it. I felt the urge to use sum but that almost feels like cheating since you could just use sum([int(i) for i in str(n)]) .

def digital_root(n):
    # convert to a string
    as_str = str(n)

    # get the value of the current first digit
    value = int(as_str[0])

    if len(as_str) > 1:
        # add the recursive return plus the value
        # for anything other than our base case.
        # pass the rest of the digits into our recursive call
        return digital_root(int(as_str[1:])) + value

    # our base case
    return value

print(digital_root(493193))

You do nothing with the result of your recursive call - thats why your code goes wrong.

Iterating via index is mostly not good - better iterate over the string directly.


This is a cleaner way for recursion using some built in python functions:

def rec_sum(n):
    sn = str(n)
    # base case - return the number
    if len(sn)==1:
        return n

    # not the base case,return whatever the recursive output returns
    return rec_sum(sum(map(int,sn)))


for n in range(1,71):
    print(f"{n:3}=>{rec_sum(n):3}", end = "|")
    if n%7 == 0:
        print()

Output:

  1=>  1|  2=>  2|  3=>  3|  4=>  4|  5=>  5|  6=>  6|  7=>  7|
  8=>  8|  9=>  9| 10=>  1| 11=>  2| 12=>  3| 13=>  4| 14=>  5|
 15=>  6| 16=>  7| 17=>  8| 18=>  9| 19=>  1| 20=>  2| 21=>  3|
 22=>  4| 23=>  5| 24=>  6| 25=>  7| 26=>  8| 27=>  9| 28=>  1|
 29=>  2| 30=>  3| 31=>  4| 32=>  5| 33=>  6| 34=>  7| 35=>  8|
 36=>  9| 37=>  1| 38=>  2| 39=>  3| 40=>  4| 41=>  5| 42=>  6|
 43=>  7| 44=>  8| 45=>  9| 46=>  1| 47=>  2| 48=>  3| 49=>  4|
 50=>  5| 51=>  6| 52=>  7| 53=>  8| 54=>  9| 55=>  1| 56=>  2|
 57=>  3| 58=>  4| 59=>  5| 60=>  6| 61=>  7| 62=>  8| 63=>  9|
 64=>  1| 65=>  2| 66=>  3| 67=>  4| 68=>  5| 69=>  6| 70=>  7|

The part sum(map(int,sn)) means: map(function,iterable) applies the int() -function to all characters in sn (strings are iterable) which is the string of your number. Then it sum() s it up and calls itself with that sum.

With recursive functions, it's generally a good idea to start with the most basic case and then incrementally add complexity.

Additionally, a trick that's useful is that taking list() of a string cuts the string into characters, ergo list("abc") returns ["a", "b", "c"] .

Using this, we get:

def digital_root(n):
    # basic scenario: n is 1 digit, ergo <10. 
    if n < 10:
         return n

    # alternative case: more than 1 digit
    # cut n into digits with a list comprehension
    # str(714) => "714", list(str(714)) => "['7', '1', '4']
    digits = [int(c) for c in list(str(n))]

    # take the digital root of the sum
    return digital_root(sum(digits))

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM