patternpythonModerate
Repeatedly multiplying digits until a single digit is obtained
Viewed 0 times
obtaineduntilmultiplyingdigitssingledigitrepeatedly
Problem
I've written code that solves a problem from codewars.com. My code passes all the tests on the codewars site. It's a simple enough problem to solve naïvely, but I would love to improve the structure.
The prompt for the problem is as follows:
Write a function,
and returns its multiplicative persistence, which is the number of
times you must multiply the digits in num until you reach a single
digit.
For example:
So my solution follows:
I was thinking I might consolidate these three little recursive functions into one function containing all three... but I'd really like input from more seasoned programmers, so I very much appreciate you taking the time to make any suggestions.
The prompt for the problem is as follows:
Write a function,
persistence, that takes in a positive parameter numand returns its multiplicative persistence, which is the number of
times you must multiply the digits in num until you reach a single
digit.
For example:
persistence(39) => 3 # Because 3*9 = 27, 2*7 = 14, 1*4=4
# and 4 has only one digit.So my solution follows:
def get_digits(num, digits=[]):
while num > 0:
digits.append(num % 10)
return get_digits(num / 10, digits)
if num == 0:
return digits
def multiply_all(digits, multiplier=1):
while len(digits) > 0:
multiplier = multiplier * digits.pop(0)
return multiply_all(digits, multiplier)
if len(digits) == 0:
return multiplier
def persistence(num, count=0):
while num >= 10:
num = multiply_all(get_digits(num))
count += 1
return persistence(num, count)
if num < 10:
return countI was thinking I might consolidate these three little recursive functions into one function containing all three... but I'd really like input from more seasoned programmers, so I very much appreciate you taking the time to make any suggestions.
Solution
Python 3.x bug
Did you know that your program outputs
This is because of the
The meaning of
Improving the solution
I was thinking I might consolidate these three little recursive
functions into one function containing all three..
What if we would get all the digits of a number by iterating over the string representation of an integer and converting every digit back to an integer -
Note that you don't actually need the while loop at all, since you are going recursive and have a
Note that you can also approach the "getting digits of a number" "mathematically" instead of converting the types back and forth:
This would also be generally faster than the first version.
Did you know that your program outputs
1 for the number 39 if executed on Python 3?This is because of the
/ division operator on this line:return get_digits(num / 10, digits)The meaning of
/ in Python 3.x was changed (PEP 238). Switching to // would be a quick fix.Improving the solution
I was thinking I might consolidate these three little recursive
functions into one function containing all three..
What if we would get all the digits of a number by iterating over the string representation of an integer and converting every digit back to an integer -
map(int, str(num)). In order to multiple the digits of a number we can use reduce() applying the operator.mul (multiplication operator) function:from functools import reduce
from operator import mul
def persistence(number, count=0):
# recursion base case - exit once the number is less than 10
if number < 10:
return count
# get new number by multiplying digits of a number
new_number = reduce(mul, map(int, str(number)))
return persistence(new_number, count + 1)Note that you don't actually need the while loop at all, since you are going recursive and have a
num < 10 base case as a recursion "exit condition".Note that you can also approach the "getting digits of a number" "mathematically" instead of converting the types back and forth:
from functools import reduce
from operator import mul
def get_digits(number):
"""Generates digits of a number."""
while number:
digit = number % 10
yield digit
# remove last digit from number (as integer)
number //= 10
def persistence(number, count=0):
if number < 10:
return count
# get new number by multiplying digits of a number
new_number = reduce(mul, get_digits(number))
return persistence(new_number, count + 1)This would also be generally faster than the first version.
Code Snippets
return get_digits(num / 10, digits)from functools import reduce
from operator import mul
def persistence(number, count=0):
# recursion base case - exit once the number is less than 10
if number < 10:
return count
# get new number by multiplying digits of a number
new_number = reduce(mul, map(int, str(number)))
return persistence(new_number, count + 1)from functools import reduce
from operator import mul
def get_digits(number):
"""Generates digits of a number."""
while number:
digit = number % 10
yield digit
# remove last digit from number (as integer)
number //= 10
def persistence(number, count=0):
if number < 10:
return count
# get new number by multiplying digits of a number
new_number = reduce(mul, get_digits(number))
return persistence(new_number, count + 1)Context
StackExchange Code Review Q#156769, answer score: 19
Revisions (0)
No revisions yet.