HiveBrain v1.2.0
Get Started
← Back to all entries
patternpythonMinor

Digital root computation with benchmarking

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
computationwithdigitalrootbenchmarking

Problem

I've read this question about computing the digital root of some integer, and wondered how it would look like in Python.

As a reminder,


"If you take the digits of any number and add them together, and then add the digits of the resulting number together, and continue doing that until you get a single digit, that single digit is the digital root of the original number."

This is not much about the algorithm performance itself, since it was shown in this answer that instead of summing the digits, you could do a simple division by 9 to get the same result. The question is more about the readability, elegance, and pythonicity (if this word exists) of my code. I checked its correctness with a tool from Thonky.

More, I'd be interested in knowing your opinion on the way I deal with sys.argv, the user interaction, and the benchmarking.

Finally, is it OK to use the int type for such long numbers? It seems to work fine even with 1000-digit numbers, but intuitively it shouldn't...

Any suggestion would be highly appreciated. Thanks.

digitalroot.py

```
# -- encoding: utf-8 --

import time
import random
import sys

def request_user_number():
while True:
try:
nb = int(raw_input('Enter a number\n'))
return nb
except (ValueError, NameError):
print 'This is not a number. Try again.'

def request_user_again():
while True:
try:
ans = str(raw_input('New computation? (y/n)\n')).lower()
if ans[0] == 'n':
again = False
print 'Bye !'
break
elif ans[0] == 'y':
again = True
break
else:
print 'Did not understand. Try again.'
except IndexError:
print 'Say something.'
return again

def digits_generator(nb):
tmp = nb
while tmp != 0:
yield tmp % 10
tmp /= 10

def digital_root(nb):
if nb ', dr, '(time :', end_time-start_tim

Solution

I think your algorithmic part is exceedingly verbose. One of the nicenesses of Python is how it can lead to code that reads almost like English. And for this particular problem, even leaving performance considerations aside, I think iteration is clearer than recursion. So I would rewrite things as:

def digits_of(number):
    """Yields the digits of an integer."""
    while number > 0:
        yield number % 10
        number //= 10

def digital_root(number):
    """Computes the digital root of an integer."""
    while number > 9:
        number = sum(digits_of(number))
    return number


I'm pretty sure my 6 year old daughter could make sense of that last function with very little help.

Code Snippets

def digits_of(number):
    """Yields the digits of an integer."""
    while number > 0:
        yield number % 10
        number //= 10

def digital_root(number):
    """Computes the digital root of an integer."""
    while number > 9:
        number = sum(digits_of(number))
    return number

Context

StackExchange Code Review Q#135488, answer score: 7

Revisions (0)

No revisions yet.