This question already has answers here:
Why does my recursive function return None?
(4 answers)
Closed 2 years ago.
I'm having this extremely strange problem and I guess it's something simple but it just makes no sense to me.
CodeWars question states:
Define a function that takes a multi digit number and multiplies each digit until you get a single digit answer, so for example persistence(39) would compute 3*9 = 27, 2*7 = 14, 1*4 = 4, return 4
I wanted to try and solve this recursively, and I have the answer, but the program will never break out of the function. I've stepped through this program multiple times and it gets to the return statement and then jumps back up into the if statement and calls persistence again.
Code below:
def persistence(n):
arg_to_list = list(str(n))
# If the argument is > one digit
if len(arg_to_list) > 1:
total = int(arg_to_list[0])
for digit in arg_to_list[1:]:
# Don't want any muplication by 0
if digit != "0":
total *= int(digit)
# Call the function again on the total
persistence(total)
else:
return n
You are not returning anything unless the number is 1-digit already, so your recursion doesn't pass over the result up. Here is what your code should look like (note the return statement just before else: - it is the only change from the original code):
def persistence(n):
arg_to_list = list(str(n))
# If the argument is > one digit
if len(arg_to_list) > 1:
total = int(arg_to_list[0])
for digit in arg_to_list[1:]:
# Don't want any muplication by 0
if digit != "0":
total *= int(digit)
# Call the function again on the total
return persistence(total)
else:
return n
Related
This question already has answers here:
Why does my recursive function return None?
(4 answers)
Closed 3 years ago.
I'm trying to solve a problem on CodeWars with the following specifications:
"Write a function, persistence, that takes in a positive parameter num and returns its multiplicative persistence, which is the number of times you must multiply the digits in num until you reach a single digit."
My solution is as follows:
def persistence(n,count = 0):
n = list(str(n))
if len(n) <= 1 :
count = 0
return count
else :
num_per = 1
for i in n :
num_per = num_per * int(i)
num_dump = num_per
if len(str(num_dump)) > 1:
count += 1
n = num_per
persistence(n,count)
else:
count = count + 1
return count
When I choose any number with more than a single digit, I get a return value of 'None'. I've narrowed down the problem to the last return statement in the second else clause. The number of counts are calculated correctly,but the return statement still returns a value of 'None'. Any help would be greatly appreciated.
Just add return before your persistence line:
return persistence(n, count)
Going off of what #jasonharper suggested, your function has an if/else statement which is decided by len(n) <= 1. If the length of n is less than 1, count (which is 0) is returned.
In your else statement however, you have another if/else statement. In your if statement, which is decided by len(str(num_dump)) > 1, you decide to recursively call the same function, however, you return no value. Therefore, your program most likely makes a lot of recursive calls but has no way of storing the values to be returned at the end of the program.
This can be fixed by replacing
persistence(n, count)
with
return persistence(n, count)
This question already has answers here:
Why is "None" printed after my function's output?
(7 answers)
Closed 3 years ago.
Learning from "Automate The Boring Stuff" by Al Sweigart. At the end of Chapter 3, the Collatz Sequence is given as practice. The output seems correct, but the last row has a 'None' in it. In the code below, I am guessing that when p = 1, it gets out of the while loop, and then there is nothing to print, so it gives a None (?). Can someone point me in the right direction of why the None is added, and how to fix it?
See code right below and example results further down:
def collatz (p):
while p != 1:
if p % 2 ==0:
p = (p//2)
print(p)
else:
p = ((3*p) + 1)
print(p)
print ('Select a number between 1 and 10')
entry = float(input())
number = round(entry)
if number >10 or number <1:
print('Your selection must between 1 and 10. Please try again')
else:
Program = collatz(number)
print (Program)
**
Example results:
If I input number as 3, I get:
3
10
5
16
8
4
2
1
None
As was already pointed out in the comments, your function returns None. I thought I'd take your function and make it a generator which you can iterate over and print the values that way. This has several advantages like making your code much more flexible and reusable:
def collatz (p):
while p != 1:
if p % 2 == 0:
p = p / 2 # You don't need the double slash here because of the if before it
else:
p = (3*p) + 1
yield p
print('Select a number between 1 and 10')
number = int(input()) # You really want int here I think and leave out the rounding
if 1 <= number <= 10: # Slightly more pythonic
for sequence_item in collatz(number):
print(sequence_item)
else:
print('Your selection must between 1 and 10. Please try again')
Feel free to ask anything or correct me on possibly wrong assumptions! :)
I'm trying to create a scientific calculator for an assignment. I'm looking for a bit of help with python syntax, and I think my design and pseudo code are doing well, but for whatever reason python isn't having any of my syntactical issues. Here is the code I have for converting binary to decimal.
I need the code to reprompt when the input is invalid, but when it does reprompt, it gets stuck in a loop of reprompting and won't give me any way out.
def bintodec(var):
power = (len(var) + 1)
value = ' '
while True:
var = input('Give a number to convert from binary to decimal: ')
for x in range(len(var)):
if (ord(var[x]) == 49):
power -= 1
value += x * (2 ** power)
if (ord(var[x]) == 48):
power -= 1
value += x * (2 ** power)
if power == -1:
break
else:
boo = True
return value
Any help is greatly appreciated!
This is pretty classic. Reading in a base is easier than writing in one.
def bintodec(var):
assert set(var) <= set("01") # Just check that we only have 0s and 1s
assert isinstance(var, str) # Checks that var is a string
result = 0
for character in var: # character will be each character of var, from left to rigth
digitvalue = ord(character) - ord("0")
result *= 2
result += digitvalue
return result
Ok, how does it work ?
Well, it reads the value from left to right. digitvalue will contain 1 or 0. For each digit we read, if it is 0, there is nothing to add the result (so result += digitvalue adds indeed 0), but we still need take into account that there is one more 0 at the end of the number.
Now, in base 10, adding a zero to the end makes a number 10 times as big. This is the same in base 2. Adding a zero at the end makes a number twice as big. This is why we multiply it by 2.
Finally, if digitvalue is 1 instead of 0, we need to add 1 to the number and result += digitvalue does it.
Note: Just for things to be clear, the two for loops below are equivalent.
for character in var:
pass # pass does nothing
for i in range(len(var)):
character = var[i]
pass
#JayF.:
Is there any way to reprompt without using assert?
I suppose you want to reprompt if the input is incorrect. You need to use a loop for that:
while True:
var = input()
if set(var) <= set("01"):
print(bintodec(var))
break # Remove this `break` statement if you want to reprompt forever
else:
# print("The input must consist of only 0s and 1s.")
pass # `pass` does nothing.
If you leave the asserts in the bintodec function, it can be done in a more pythonic way, using exception handling:
while True:
var = input()
try:
print(bintodec(var))
break
except AssertionError:
print("The input must consist of only 0s and 1s.")
This question already has answers here:
Implementing the collatz function using Python
(8 answers)
Closed 5 years ago.
Note: I was trying to figure out why my while statement did not evaluate to False when the integer was, so I don't believe this is a duplicate
Doing an automating the boring stuff exercise in python where the program receives an input and reduces it to 1 using the following algorithm.
#even / 2
#odd * 3 + 1
def collatz():
print("Enter number:")
number = input()
try:
data = int(number) # Input Validation
while int(data) != 1:
if data % 2 == 0: #Number is even
data = int(data/2)
print(data)
if data % 2 == 1: # Number is odd
data = int(3*data+1)
print(data)
except:
print("Please input a valid value")
collatz()
collatz()
Instead of the while loop breaking, when the number is reduced to 1. The loop continues and it multiplies 1 by 3 and adds 1(Just as normal odd number). Btw many int conversions were done as I thought it may have returned a floating point.
So please tell me where are the unncessary int conversions and how to break it using a while statement. Any cleanup to code is appreciated
There are a few things that you should neaten up to make your code work properly and just generally better:
Rename data to n, this isn't going to make much of a difference, but I would say it just makes more sense.
There is no need to do endless conversions to int, n only needs to be converted from a string to an integer once.
Don't put your entire code in a function then call it once, instead have the main algorithm in a smaller function which you then can call from the main body of your code or even create another function to call the algorithm which handles the inputting side of things.
Use the integer division operator (//) instead of the floating point divider (/), since the number will be even, you can be sure that the decimal place will be 0.
You don't need to check if n % 2 is 0 and then on the next line check if it n % 2 is 1, you can just use an if ... else clause.
And that's about it! Here's what it looks like:
#even / 2
#odd * 3 + 1
def collatz(n):
while n != 1:
if n % 2 == 0: #Number is even
n = n // 2
else:
n = n * 3 + 1
print(n)
number = input("Enter number:")
try:
number = int(number)
collatz(number)
except ValueError:
print("Please input a valid value")
And a test shows it works (input of 24):
12
6
3
10
5
16
8
4
2
1
Note - Go down to the edits if you want the more recent code, look here if you want to see the original question. I have made edits to the code, however, so mistakes in this code block may be outdated.
As a self-taught Python 3 programmer, I have been working on a way to simplify radical expressions. The one part of the program that does not work, however, is the square factorization. I have a function that detects square numbers, which works fine. The function that does not work is the following-
def sqfactorslist(num):
factors = []
counter = num // 2 + 1
while counter > 0:
if counter == 1:
factors.append(num) #if no square ints other than 1 square into num, append and finish.
while is_square(counter) == True and counter != 1: #If counter is a valid square integer, append it's square and subtract it from num.
if (counter ** 2) >= num:
factors.append(counter ** 2)
num -= counter ** 2
else: #Else, continue with a program.
break
if counter > 0:
counter -= 1 #If counter more than 0, subtract 1 from it
else:
break #If number is equal to or less than 0, break
return factors #If the input is 32, this should return 16 and 2.
It doesn't return anything other than an infinite loop. Anyone know whats wrong?
Edit 1 -- I have changed the program so that it runs, but now I have a stranger issue: If I input a square number as num, for example 16, I get a number larger than the input, e.x. 81, in the return list. I get no returned elements for a non-square number.
To make it run, I indented the first if statement after the end of the second while loop.
Edit 2 -- I have changed the program again, but I come up with another issue similar to the one above. After eliminating another mistake, where I squared numbers already shown to be square, found in the second while loop, the program now has a new problem - If I use a non-square integer, it returns an empty list, and if I use a square integer, like 16, it gives me an infinite loop. Current code shown below --
def findsqfactors(num):
factors = []
counter = num // 2 + 1
while counter > 0:
if counter == 1:
factors.append(num) #If no square ints other than 1 square into num, append then finish.
while is_square(counter) == True and counter != 1: #
if counter >= num:
factors.append(counter)
num -= counter
else:
break
if counter > 0:
counter -= 1
else:
break
return factors