recursive functions keep printing zero multiple times - python

I am doing a program of say digit in python using recursion and i want that if digit==0 return nothing.
Code:
# Q1
# Say digit
# i/p = 412 - o/p = four one two
list = ['zero','one','two','three','four','five','six','seven','eight','nine']
n=412
def say_digit(n, list):
if n==0:
return ''
digit = int(n % 10)
n = n / 10
say_digit(n, list)
print(list[digit], end=' ')
return ''
if __name__ == "__main__":
n=int(input("Enter Number: "))
ans = say_digit(n, list)
print(ans)
Output:

The code does a division by 10 at each iteration. But there's no guarantee this will reach 0. In Python3, it does a floating point division. You can get to 0 with integer division (using // instead of /).
Here's an updated version:
# Q1
# Say digit
# i/p = 412 - o/p = four one two
numbers = ['zero','one','two','three','four','five','six','seven','eight','nine']
n=412
def say_digit(n, numbers):
if n==0:
return ''
digit = int(n % 10)
n = n // 10
return say_digit(n, numbers) + ' ' + numbers[digit]
if __name__ == "__main__":
n=int(input("Enter Number: "))
ans = say_digit(n, numbers)
print(ans)
It also translates each digit in the words from list.
Ideally, one shouldn't shadow built-in names like 'list'. To avoid that, this version uses the name 'numbers'.

Use // instead of /
i.e. n = n // 10
/ gives float and // gives int

Related

Code that have exact function like oct() in Python

I need code that have exact function like oct() in Python but without using any other methods and functions.
I wrote this, but I think it's so large and also I don't want use range and len:
def get_oct(x):
next_step = [x]
r_mod = []
while True:
x /= 8
i = int(x)
next_step.append(i)
if int(x / 8) == 0:
break
for m in range(len(next_step)):
next_step[m] %= 8
j = int(next_step[m])
r_mod.append(j)
t_mod = r_mod[::-1]
return "0o" + "".join(str(e) for e in t_mod)
entry = int(input("Enter a number: "))
print(get_oct(entry))
If you want this to work like the built-in oct(), you need to account for zero and negative numbers. A nicer way to deal with this is to use the function divmod() the returns the result of integer division and the remainder. Just keep doing that until the value is zero:
def get_oct(x):
if x == 0: return '0o0'
prefix = '-0o' if x < 0 else '0o'
x = abs(x)
res = ''
while x:
x, rem = divmod(x, 8)
res = str(rem) + res
return (prefix + res)
assert(get_oct(80) == oct(80))
assert(get_oct(1) == oct(1))
assert(get_oct(0) == oct(0))
assert(get_oct(-2) == oct(-2))
assert(get_oct(-201920) == oct(-201920))
assert(get_oct(12345678910) == oct(12345678910))
If all that is needed is to print in octal without oct() function,string formatting could be the easiest option.
num = int(input("Enter a number: "))
print("{:o}".format(num))
Output:
Enter a number: 10
12
This is also possible with string variable
num = int(input("Enter a number: "))
s = "{:o}".format(num)
print(s)
Output:
Enter a number: 10
12

Sum of digits untill reach single digit

I set an algorithm which sum a number's digits but I couldn't make it till single digit. It only work for one step.
For example:
a=2, b=8
a^b=256 = 6+5+2 = 13
But I want to reach single digit, like:
a^b=256 = 6+5+2 = 13 = 3+1 = 4
Below you can see my codes.
a = int(input("Enter a value"))
b = int("Enter second value")
number = pow(a, b)
sum= 0
while float(number) / 10 >= .1:
m = number % 10
sum += m
number = number // 10
if float(number) / 10 > .1:
print(m, end=" + ")
else:
print(m, "=", sum)
Here you go:
n = 256
while n > 9:
n = sum(int(i) for i in str(n))
print(n)
So whats going on? str(n) converts n to a string, strings in python can be iterated over so we can access digit by digit. We do this in a generator, converting each digit back to a integer, int(i) for i in str(n), we use sum to sum the elements in the generator. We repeat this process until n is a single digit.
Added a solution that gives the calculation explicitly:
def sum_dig(n):
_sum = sum(int(i) for i in str(n))
explained = "+".join(list(str(n)))
return _sum, explained
n = 256
s = ""
while n > 10:
n, e = sum_dig(n)
s+= f'{e}='
s += str(n)
print(s)
yields:
2+5+6=1+3=4
you can try this.
a = int(input("Enter a value"))
b = int(input("Enter second value"))
number = pow(a, b)
result = str(a)+'^'+str(b) + ' = ' + str(number)
while number > 9:
digit_sum = sum(map(int, str(number)))
result += ' = ' + '+'.join(str(number)) + ' = ' + str(digit_sum)
number = digit_sum
print ( result )
for a=2, b=8 result:
2^8 = 256 = 2+5+6 = 13 = 1+3 = 4
This produces the output in the format OP asked for:
a = int(input("Enter a value: "))
b = int(input("Enter second value: "))
n = pow(a, b)
while n >= 10:
nums = [i for i in str(n)]
op = "+".join(nums)
n = eval(op)
print("{}={}".format(op, n))
Logic:
Store the input in an array of individual numbers as strings.
Create the summation string using "+".join(nums) - for the output print.
Calculate the sum using eval(op) which works on strings (a built-in function) - store in n.
Print the summation string and what it equals.
Output:
Enter a value: 2
Enter second value: 8
2+5+6=13
1+3=4
Enter a value: 2
Enter second value: 6
6+4=10
1+0=1
Enter a value: 2
Enter second value: 50
1+1+2+5+8+9+9+9+0+6+8+4+2+6+2+4=76
7+6=13
1+3=4
sol = 0
if (a^b)%9==0:
sol = 9
else:
sol = (a^b)%9

Why does this Python code not work?

Please help, I cannot figure out why this code does not work. I think the first loop runs forever but I don't know why!
def NTN():
list1 = []
count = 0
number = 0
Start = input('Type Start Number')
while number != Start:
count = count + 1
number = number + count
Stop = input('Type Stop Number')
while number != Stop:
count = count + 1
number = number + count
if number != Stop:
(list1).append(number)
return (list1)
print(NTN())
You are increasing number by increasing amounts in every iteration. Here's an idea of how it is increasing. Assume Start = 4
After 1 loop, count = 1 and number = 1, increase of 1
After 2 loops, count = 2 and number = 3, increase of 2
After 3 loops, count = 3 and number = 6, increase of 3
Since number is never really equal to 4, the loop never ends. What you need probably is while number <= Start. That would terminate the loop after 3 iterations when number is past 4.
change "number != Start" and "number != Stop" to "number < Start" and "number < Stop" in all places, and it should work.
What went wrong: if Start is 2, then in the first iteration of the while loop, count becomes 0+1=1 and number becomes 0+1=1; in the second iteration, count becomes 1+1=2 and number becomes 1+2=3, which bypasses 2. Since your while loop only ends when number is equal to Start, it never ends.
A couple of side-points:
By convention Python variable and function names are lower-case.
input() returns a string; if you want a number you have to convert it ie with int() or float(). (Note: if you are using Python 2.x input() calls eval() which is really awful design - you should be using int(raw_input()) instead.)
so,
# This code assumes Python 3.x
from math import ceil, sqrt
def get_int(prompt):
"""
Prompt until an integer value is entered
"""
while True:
try:
return int(input(prompt))
except ValueError:
print("Please enter an integer!")
def tri(n):
"""
Return triangular number n,
ie the sum of (1 + 2 + ... + n)
"""
# using Gaussian sum
return n * (n + 1) // 2
def reverse_tri(t):
"""
For positive integer t,
return the least positive integer n
such that t <= tri(n)
"""
# derived by quadratic formula from
# n * (n + 1) // 2 >= t
return int(ceil(((sqrt(8 * t + 1) - 1) / 2)))
def ntn(start, stop):
"""
Return a list of triangular numbers
such that start <= tri < stop
"""
a = reverse_tri(start)
b = reverse_tri(stop)
return [tri(n) for n in range(a, b)]
def main():
start = get_int('Enter a start number: ')
stop = get_int('Enter a stop number: ')
lst = ntn(start, stop + 1) # include stop number in output
print(lst)
if __name__ == "__main__":
main()

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)

Adding the digits of an int and 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)))

Categories

Resources