Python recursive function returning none after completion - python-3.x

My code is supposed to countdown from n to 1. The code completes but returns None at the end. Any suggestions as to why this is happening and how to fix it? Thanks in advance!
def countdown(n):
'''prints values from n to 1, one per line
pre: n is an integer > 0
post: prints values from n to 1, one per line'''
# Base case is if n is <= 0
if n > 0:
print(n)
countdown(n-1)
else:
return 0
def main():
# Main function to test countdown
n = eval(input("Enter n: "))
print(countdown(n))
if __name__ == '__main__':
main()

print(countdown(n)) prints the value returned by countdown(n). If n > 0, the returned value is None, since Python functions return None by default if there is no return statement executed.
Since you are printing values inside countdown, the easiest way to fix the code is to simply remove the print call in main():
def countdown(n):
'''prints values from n to 1, one per line
pre: n is an integer > 0
post: prints values from n to 1, one per line'''
# Base case is if n is <= 0
if n > 0:
print(n)
countdown(n-1)
def main():
# Main function to test countdown
n = eval(input("Enter n: "))
countdown(n)
if __name__ == '__main__':
main()
Edit: Removed the else-clause since the docstring says the last value printed is 1, not 0.

Remove the print(countdown(n)) and replace it with just countdown(n).
What happens is your countdown function returns nothing when n is greater than 0, so that print statement is printing None. You can also remove your else statement in countdown(n) - since you never care about the return value of countdown, it serves no purpose.
def countdown(n):
'''prints values from n to 1, one per line
pre: n is an integer > 0
post: prints values from n to 1, one per line'''
# Base case is if n is <= 0
if n > 0:
print(n)
countdown(n-1)
# No need to return a value from here ever - unused in the recursion and
# you don't mention wanting to have zero printed.
#else:
# return 0
def main():
# Main function to test countdown
n = eval(input("Enter n: "))
# Don't print the result of countdown - just call it
#print(countdown(n))
countdown(n)
if __name__ == '__main__':
main()

You want to return the recursive call to the next invocation of countdown:
def countdown(n):
'''prints values from n to 1, one per line
pre: n is an integer > 0
post: prints values from n to 1, one per line'''
# Base case is if n is <= 0
if n > 0:
print(n)
return countdown(n-1)
else:
return 0
def main():
# Main function to test countdown
n = eval(input("Enter n: "))
print(countdown(n))
if __name__ == '__main__':
main()
In this way, when the base case is reached, the return value of 0 should propagate back up the stack and be returned.
Unfortunately, however, since your base case returns 0, this results in the printing of 0. But, if you want to return something (think about whether or not you actually need to in this case) this would be how you do it.
If you don't need to return anything, then you don't need to print the result. Further modify
print(countdown(n))
to
countdown(n)

Related

How to find the first odd digit in an integer recursively

I am new to python and am trying to get more comfortable with recursion. I am trying to find the first odd digit of a integer recursively. If there are no odd digits found return -1. Whenever I run this code I always get 35 instead of just 5.
This is what I have tried
def first_odd(n):
if n == 0:
return 0
elif n % 2 == 1:
return first_odd(n//10) * 10 + n%10
else:
return first_odd(n//10)
print(first_odd(2345))
If I understand your recent comment to Tarik correctly, it sounds like you want a function that will return the first odd digit scanning an integer right to left and if no odd digits are found then return -1. For example, in your original post you stated that with the integer 2345 you expected the value of 3, but based on your comment it sounds like 5 would be the correct answer scanning right to left, right? If so, then the following code should meet that description.
from random import randint
def find_rightmost_odd_digit(number):
while number:
rightmost_digit = number % 10
if rightmost_digit % 2:
return rightmost_digit
number = number // 10
return -1
for _ in range(10):
number = randint(0, 1000)
print(f"{number:>10}{find_rightmost_odd_digit(number):>4}")
Output:
387 7
88 -1
639 9
196 9
986 9
232 3
82 -1
907 7
948 9
214 1
You were basically on the correct track but just included an extra recursion you didn't need. Consider:
def first_odd(n):
if n == 0:
return -1
if n % 2 == 1: # number is odd, return last digit
return n % 10
return first_odd(n // 10)
If this works as intended, then I might implement it as follows to combine a couple of the divisions:
def first_odd(n):
if n == 0:
return -1
quotient, remainder = divmod(n, 10)
if remainder % 2 == 1: # remainder is odd, return it
return remainder
return first_odd(quotient)
Is there also a way to find the first odd digit from left to right
using 1 parameter?
from math import log10
def first_left_odd(n):
if n == 0:
return -1
power = 10 ** int(log10(n))
digit = n // power
if digit % 2 == 1:
return digit
return first_left_odd(n - digit * power)
Or if using the math library and/or log10() is an issue, then:
def first_left_odd(n):
if n < 10:
return n if n % 2 == 1 else -1
result = first_left_odd(n // 10)
if result != -1:
return result
return first_left_odd(n % 10)
Building complex programs is a matter of combining several simple programs. For this problem I would write a program that breaks a number into digits, and one that checks if any particular number is_odd -
def first_odd(n):
for d in digits(n):
if is_odd(d):
return d
return None
We can write digits and is_odd easily -
def is_odd(n):
return n & 1
def digits(n):
if n < 0:
yield from digits(n * -1)
elif n < 10:
yield n
else:
yield from digits(n // 10)
yield n % 10
print(first_odd(2345)) # 3
print(first_odd(6804721)) # 7
print(first_odd(2468)) # 9
print(first_odd(-465321)) # 5
This might do it:
def first_odd(n, digit):
if n == 0:
return None
elif n % 2 == 1:
return digit
else:
return first_odd(n//10, digit+1)
first_odd(2345, 0)
If you want the first digit to be 1, pass 1 instead of 0
Ok, this is for left to right:
def first_odd(n, digit):
if n == 0:
return None
pos = first_odd(n//10, digit+1)
if pos is None and n % 2 == 1:
return digit
else:
return pos

Recursively calling a second function inside a function

I have this code that counts up -3, -2, -1. I have also written another that counts down 3, 2, 1. If the condition is true for another after an input, the program should stop. For Example, The input i enter -3 for negatives it gives -3, -2, -1, if i enter positive number like 3, the result should be 3, 2, 1 in a single combined code.
I have tried to put a function into an if statement of the first function but fails with "NameError: name 'countdown' is not defined" for count down but count up works.
print('+=+=+=+=+=+=+=+=+=+=+=+=+ F1')
#count up
def countup(n):
if (n >= 0):
print('Hello')
if n==0:
print('Blastoff!')
else:
print(n)
countdown(n-1)
else:
print(n)
nth = n + 1
countup(nth)
result = int(input('Enter Number: '))
countup(result)
Have you tried replacing the second else with elif? And fixing the indenting? The resulting code should be this:
print('+=+=+=+=+=+=+=+=+=+=+=+=+ F1')
#count up
def countup(n):
if (n >= 0):
print('Hello')
if n==0:
print('Blastoff!')
elif (condition):
print(n)
countdown(n-1)
else:
print(n)
nth = n + 1
countup(nth)
result = int(input('Enter Number: '))
countup(result)
I solve the problem by doing this code below:
def countup(n):
if (n >= 0):
print('Blastoff 1')
else:
print(n)
nth = n + 1
return countup(nth);
def zero(n):
if (n==0):
print('You have erntered 0 program exiting')
exit()
def countdown(n):
if (n <= 0):
print('explode 2')
else:
print(n)
nth = n - 1
return (countdown(nth))
num = int(input("Enter number: "));
if (num <= 0):
print(countup(num))
elif num == 0:
print(zero(num))
else:
print(countdown(num))
The output is either negative or positive, regardless of what integer you fuse in

Count not incrementing properly in python while loop

Can anyone tell me why when I input 1, 2, 3, and 4 into this code, my output is 6, 2, 3.00? I thought that every time my while loop evaluated to true it would increment the count by one, but the output is not making sense. It's taking the total of 3 of the numbers, but only 2 for the count? I'm probably just overlooking something so an extra pair of eyes would be awesome.
def calcAverage(total, count):
average = float(total)/float(count)
return format(average, ',.2f')
def inputPositiveInteger():
str_in = input("Please enter a positive integer, anything else to quit: ")
if not str_in.isdigit():
return -1
else:
try:
pos_int = int(str_in)
return pos_int
except:
return -1
def main():
total = 0
count = 0
while inputPositiveInteger() != -1:
total += inputPositiveInteger()
count += 1
else:
if count != 0:
print(total)
print(count)
print(calcAverage(total, count))
main()
The error with your code is that on this piece of code...
while inputPositiveInteger() != -1:
total += inputPositiveInteger()
You first call inputPositiveInteger and throw out the result in your condition. You need to store the result, otherwise one input out of two is ignored and the other is added even if it is -1.
num = inputPositiveInteger()
while num != -1:
total += num
count += 1
num = inputPositiveInteger()
Improvements
Although, note that your code can be significantly improved. See the comments in the following improved version of your code.
def calcAverage(total, count):
# In Python3, / is a float division you do not need a float cast
average = total / count
return format(average, ',.2f')
def inputPositiveInteger():
str_int = input("Please enter a positive integer, anything else to quit: ")
# If str_int.isdigit() returns True you can safely assume the int cast will work
return int(str_int) if str_int.isdigit() else -1
# In Python, we usually rely on this format to run the main script
if __name__ == '__main__':
# Using the second form of iter is a neat way to loop over user inputs
nums = iter(inputPositiveInteger, -1)
sum_ = sum(nums)
print(sum_)
print(len(nums))
print(calcAverage(sum_, len(nums)))
One detail worth reading about in the above code is the second form of iter.

Finding the logical error in my code to get first 50 primes

I'm trying to write my own formula to find a prime number, but it does not completely work and I cannot find the flaw in my logic. Bare in mind I have taken a look around but cannot find an algorithm that I find similar to mine.
My code:
#Challenge 7
prime = []
num = 0
found = False
while found == False:
if num == 0 or num == 1:
num+=1
else:
for value in range(2, num+1):
if len(prime) == 50:
print('Found all')
found = True
break
if num % value == 0:
num+=1
else:
if num not in prime:
prime.append(num)
else:
pass
print(prime)
This code works for first few primes (3, 5, 7...)
but it also gives incorrect values like 10, and I don't understand why. If someone could explain it to me so that I can understand where the logical mistake is, I'd appreciate it.
The error comes from this part
if num % value == 0:
num+=1
else:
if num not in prime:
prime.append(num)
else:
pass
You assume that the integer is a prime as soon as we find the first occurence of a non-divisor. But the def for primes is that every integer in the interval [2..prime] is a non-divisor. How do we check if any number does not have any divisors?
def isPrime(x):
for v in range(2, x):
if (x % v == 0):
return False;
return True;
Something like this would work to check if any given number is a prime or not. And since we now have taken the isPrime part out of the main loop, we no longer need a for loop inside the while. Something like this would do
def isPrime(x):
for v in range(2, x):
if (x % v == 0):
return False;
return True;
prime = [}
num = 2
found = False
while found == False:
if len(prime) == 50:
print("found all")
found = True
break
if(isPrime(num)):
print(num)
prime.append(num)
num+=1
else:
num+=1
If you set a breakpoint for when num == 10 you will see the problem clearly.
When you start doing you division check inside of for value in range(2, num + 1): the second number is 3, so num (10) modulo value (3) is 1, which is your test for determining a prime. What your test should be is that it not divisible by any number less than it (less than half is actually sufficient since you check with 2 anyway).
So, consider instead:
else:
is_indivisible = True
# loop through all numbers less than it not including itself
# (because x % x == 0)
for value in range(2, num - 1):
# it is only indivisible if it was previously indivisible
# And the check is same as before, modulo != 0
is_indivisible = is_indivisible and (num % value != 0)
if not is_indivisible:
break
# if it is indivisible and it doesn't exist in prime list yet
if is_indivisible and num not in prime:
prime.append(num)
# move on to the next number
num += 1

Using Recursive Functions in Python to find Factors of a Given Number

Have tried searching for this, but can't find exactly what I'm looking for.
I want to make a function that will recursively find the factors of a number; for example, the factors of 12 are 1, 2, 3, 4, 6 & 12.
I can write this fairly simply using a for loop with an if statement:
#a function to find the factors of a given number
def print_factors(x):
print ("The factors of %s are:" % number)
for i in range(1, x + 1):
if number % i == 0: #if the number divided by i is zero, then i is a factor of that number
print (i)
number = int(input("Enter a number: "))
print (print_factors(number))
However, when I try to change it to a recursive function, I am getting just a loop of the "The factors of x are:" statement. This is what I currently have:
#uses recursive function to print all the letters of an integer
def print_factors(x): #function to print factors of the number with the argument n
print ("The factors of %s are:" % number)
while print_factors(x) != 0: #to break the recursion loop
for i in range(1,x + 1):
if x % i == 0:
print (i)
number = int(input("Enter a number: "))
print_factors(number)
The error must be coming in either when I am calling the function again, or to do with the while loop (as far as I understand, you need a while loop in a recursive function, in order to break it?)
There are quite many problems with your recursive approach. In fact its not recursive at all.
1) Your function doesn't return anything but your while loop has a comparision while print_factors(x) != 0:
2) Even if your function was returning a value, it would never get to the point of evaluating it and comparing due to the way you have coded.
You are constantly calling your function with the same parameter over and over which is why you are getting a loop of print statements.
In a recursive approach, you define a problem in terms of a simpler version of itself.
And you need a base case to break out of recursive function, not a while loop.
Here is a very naive recursive approach.
def factors(x,i):
if i==0:
return
if x%i == 0:
print(i)
return factors (x,i-1) #simpler version of the problem
factors(12,12)
I think we do using below method:
def findfactor(n):
factorizeDict
def factorize(acc, x):
if(n%x == 0 and n/x >= x):
if(n/x > x):
acc += [x, n//x]
return factorize(acc, x+1)
else:
acc += [x]
return acc
elif(n%x != 0):
return factorize(acc, x+1)
else:
return acc
return factorize(list(), 1)
def factors(x,i=None) :
if i is None :
print('the factors of %s are : ' %x)
print(x,end=' ')
i = int(x/2)
if i == 0 :
return
if x % i == 0 :
print(i,end=' ')
return factors(x,i-1)
num1 = int(input('enter number : '))
print(factors(num1))
Recursion is a functional heritage and so using it with functional style yields the best results. This means avoiding things like mutations, variable reassignments, and other side effects. That said, here's how I'd write factors -
def factors(n, m = 2):
if m >= n:
return
if n % m == 0:
yield m
yield from factors(n, m + 1)
print(list(factors(10))) # [2,5]
print(list(factors(24))) # [2,3,4,6,8,12]
print(list(factors(99))) # [3,9,11,33]
And here's prime_factors -
def prime_factors(n, m = 2):
if m > n:
return
elif n % m == 0:
yield m
yield from prime_factors(n // m, m)
else:
yield from prime_factors(n, m + 1)
print(list(prime_factors(10))) # [2,5]
print(list(prime_factors(24))) # [2,2,2,3]
print(list(prime_factors(99))) # [3,3,11]
def fact (n , a = 2):
if n <= a :
return n
elif n % a != 0 :
return fact(n , a + 1 )
elif n % a == 0:
return str(a) + f" * {str(fact(n / a , a ))}"
Here is another way. The 'x' is the number you want to find the factors of. The 'c = 1' is used as a counter, using it we'll divide your number by 1, then by 2, all the way up to and including your nubmer, and if the modular returns a 0, then we know that number is a factor, so we print it out.
def factors (x,c=1):
if c == x: return x
else:
if x%c == 0: print(c)
return factors(x,c+1)

Resources