I am trying to write code to find whether a given number is odd or even using recursion in Python.
When I execute my code, the recursive function descends down to 0 correctly but then doesn't halt, and keeps going with negative values. I expect it to stop when it reaches 0.
How to make sure the function returns after it reaches zero?
My code:
def odeven(n):
if n%2 == 0:
print("even no. : ",n)
elif n%2 != 0:
print("odd no. : ",n)
elif (n == 0):
return 0
return odeven(n-1)
result = odeven(10)
print("result odd ={}".format(result))
Fixing the most obvious mistake
Your main issue is that the branch elif (n == 0): will never be reached because 0 is even, so 0 gets caught in the first branch if n%2 == 0:
You can fix it by changing the order of the branches:
def odeven(n):
if (n == 0):
return 0
elif n%2 == 0:
print("even no. : ",n)
else: # n%2 != 0
print("odd no. : ",n)
return odeven(n-1)
result = odeven(10)
print("result odd ={}".format(result))
Output:
even no. : 10
odd no. : 9
even no. : 8
odd no. : 7
even no. : 6
odd no. : 5
even no. : 4
odd no. : 3
even no. : 2
odd no. : 1
result odd =0
Further improvements
You can figure out whether a number n is odd or even simply by checking the value of n % 2. There is no need for recursion here.
Presumably this is an exercise that was given by a teacher who wants you to use recursion to figure out whether n is odd or even without using %. This is terribly inefficient and has no use in practice, and is purely an exercise to learn about recursion. In that case, do not use %. Operator % solves the whole problem by itself so if you use it, you don't need to use recursion. It defeats the purpose of the exercise.
Compare the two following functions:
def oddeven_direct(n):
if (n % 2 == 0):
return 'even'
else:
return 'odd'
def oddeven_recursive(n):
if (n == 0):
return 'even'
elif (n == 1):
return 'odd'
elif (n > 1):
return oddeven_recursive(n-2)
elif (n < 0):
return oddeven_recursive(-n)
print(oddeven_direct(10))
print(oddeven_recursive(10))
Note that I did not call function print inside the function. The function returns a result, which is 'even' or 'odd', and doesn't print anything. This is more consistent. If the user calling the function wants to print something, they can call print themselves.
A variation
Notice how the recursive call jumped from n to n-2? This is because I know that n and n-2 will have the same parity (both odd or both even); and we have two base cases, 0 and 1, to which we're guaranteed to arrive when jumping 2 by 2.
If we had jumped from n to n-1 instead, we'd have run into an issue because n and n-1 have different parity (odd and even or even and odd), so we need some way to keep track of this change of parity during the recursion.
This can be achieved by implementing two distinct functions, is_odd and is_even, and using the recursion to express the facts "n is odd if n-1 is even" and "n is even if n-1 is odd".
Since those functions have names that sound like yes/no question, or true/false question, we will make them return True or False, which are called boolean values.
def is_odd(n):
if n == 0:
return False
else:
return is_even(n-1)
def is_even(n):
if n == 0:
return True
else:
return is_odd(n-1)
print('10 is even? {}'.format(is_even(10)))
print('10 is odd? {}'.format(is_odd(10)))
Note that python knows boolean values very well and we can make the code shorter using the two lazy logic operators and and or:
def is_odd(n):
return n != 0 and is_even(n-1)
def is_even(n):
return n == 0 or is_odd(n-1)
print('10 is even? {}'.format(is_even(10)))
print('10 is odd? {}'.format(is_odd(10)))
You get an error, because you call the function inside the function and never stop that function call so it recurses over and over again. Python allows recursion but only until a defined end is reached
To change this limit:
https://www.geeksforgeeks.org/python-handling-recursion-limit/
Also your recursion gets into minus, because you call your function attribute (= (n)) allways one number lower than the function call before:
Your function is now called with
odeven(9)
and so on until it reaches -985, which is in your case the maximum recursion depth which results in:
[Previous line repeated 992 more times]
File "/python/test.py", line 5, in odeven
print("odd no. : ",n)
Related
Lately am trying to do some Python programming, so am doing some mathematical exercices in some website.
I came across this example and at first I didn't understand the exercise. So I checked the solution to at least understand the question. As a consequence I found myself learning some coding tricks (like the while True loop).
The exercise is simple:
Write a Python program to find the smallest multiple of the first n numbers. Also, display the factors.
Below is the code:
def smallest_multiple(n):
if (n<=2):
return n
i = n * 2
factors = [number for number in range(n, 1, -1) if number * 2 > n]
print(factors)
while True:
for a in factors:
if i % a != 0:
i += n
break
if (a == factors[-1] and i % a == 0):
return i
My questions are:
Why does he create a list of numbers that are superior to the input by a factor of 2?
And then the while loop is just difficult to undestand. Could someone please explain it to me (I mean the content of the loop)?
I think we have here a tiny mixture of mathematic question and programming.
first of all, please note that the spaces are important in coding. see how the code should look like. (with the spaces)
def smallest_multiple(n):
if (n<=2):
return n
i = n * 2
factors = [number for number in range(n, 1, -1) if number * 2 > n]
print(factors)
while True:
for a in factors:
if i % a != 0:
i += n
break
if (a == factors[-1] and i % a == 0):
return i
1- Why does he create a list of numbers that are superior to the input by a factor of 2 ?
Answer : because the numbers that have their double smaller than the highest number will not affect / change the result. (This is a maths question) you can check that by removing the condition and you will see that you will get the same result (same smallest multiple)
2-And then the while loop is just difficult to understand. Could someone please explain it to me (I mean the content of the loop)? Thanks for your response?
Answer : The loop is using the boolean True as the code will only stops until it finds the smallest multiple for the first n numbers. the reason of the coder doing this because he has used the keyword return that will help him to exit the function, ultimately exiting the while loop.
The loop uses the value i which is the first multiple of the highest number of the first n numbers, meaning the double of the value n. Then will check if this first multiple (meaning i) is not dividable (i % a != 0) by the numbers in the list starting from the highest.
if i % a != 0:
i += n
break
this condition is there to increase the value of i as soon as i is not dividable by any number of the first n numbers meaning that the code keeps searching through the multiples of n (n being the highest number of the list) until i is dividable by all the numbers in the list
once the i value is able to satisfy the condition below
if (a == factors[-1] and i % a == 0):
then the while loop is exited through the keyword return which exits the function and the i value is sent as a response to the function call through the line return i
also note that factors[-1] is the last item (number) of the list.
I hope the above make sense and is clear to you.
Given an integer, , perform the following conditional actions:
If is odd, print Weird
If is even and in the inclusive range of 2 to 5, print Not Weird
If is even and in the inclusive range of 6 to 20, print Weird
If is even and greater than 20, print Not Weird
Every time I run the code, it only executes the else statement else: print("lol") , whether I type any value from 1 to 25.
What's wrong?
n = input("Enter a number here: ")
num = int(n)
if (num % 2) == 0 >= 2 and (num % 2) == 0 <= 5:
print("Not Weird")
elif num % 2 == 0 >= 6 and num % 2 == 0 <= 20:
print("Weird")
elif num % 2 == 0 > 20:
print("Not Weird")
else:
print("lol")
(num % 2) == 0 >= 2 is not the correct way to check if a number is even and in the range you want. If you want to check if num is even and in that range, you'd do something like:
(((num % 2) == 0) and (1 < num <= 5))
As others have pointed out your conditions are not written correctly. Here's the first part to get you started (if the number is odd, and if the number is even and between 2 and 5):
n = input("Enter a number here: ")
num = int(n)
isEven = (num % 2) == 0
if not isEven:
print("Weird")
elif 2 <= num <= 5:
print("Not Weird")
Just as Random Davis said , the problem is in precedence(or whatever it is called sorry XD) so what it does is :
when you check for [(num % 2) == 0 >= 2] : what it does is first checks if num is even[(num % 2)] and then it checks the relation between 0 and 2[0 >= 2] and then equates [ [(num % 2){maybe true or false} == (0 >= 2){always false}]] which results in a LOGICAL ERROR
Rather what you should do is this
(((num % 2) == 0) and (1 < num <= 5)) {just as Random Davis said.}
what it does is checks whether number is even or not[(num % 2) == 0)] and then if number is between 1 and 5[(1 < num <= 5)] and then cheks if both are true or not.
Hope you understand what I am trying to say.
There are a couple of problems with your solution. There is nothing wrong with your if-else statements. They are valid, but are not doing what you want. Looking at the first if:
if (num % 2) == 0 >= 2 and (num % 2) == 0 <= 5:
print("Not Weird")
You first use modulo and test for equality with 0, which is a reasonable test for even vs odd. However, you then compare the boolean result of the even-add test with the number 2. You want to test num with 2, not the boolean of evenness with 2. Testing a boolean result for >= 2 always comes out false. That is True >= 2 is False; and False >=2 is False. Python is smart enough to know that False and (anything else) will be false, so Python won't even evaluate the rest of the statement.
So to test if a number is even and in the range of 2 to 5 inclusive you should want to do:
if num % 2 == 0 and 2 <= num <= 5 :
print("Not Weird")
A few words about Python: Python differs from other languages in that the form "2 <= num <= 5" is a legal construct. It is darn convenient, but atypical among languages. In other languages the initial 2<=num results in a boolean and then then you would get an error comparing a boolean to 5. It is interesting that Python does not throw an error but results in a boolean. Though Python is atypical it is useful. Other languages would require something like
if (2 <= num) and (num <= 5) then # Not a Python statement!
Another oddity is that the and operator is lower precedence than the other comparison operators. In other languages and is higher or equal. The Python rules of precedence let you use "num % 2 == 0 and 2 <= num <= 5", so the evenness test and the double inequality run before the "and", so you get a natureal human result. BUT IT IS DIFFERENT FROM OTHER LANGUAGES. You will probably learn a lot of languages over the years. Appreciate how they work.
I'll let you figure out the rest of the statements in your original solution. However, there is another problem: You don't handle odd numbers in your solution correctly, since you are printing out lol. For debugging you are doing the correct thing, since the printing of "Weird" for odd numbers is an ambiguous result. If you did that on purpose for debugging, CONGRATULATIONS!, you are thinking like a programmer digging through your program.
I submit that your approach is a bit of a brute force approach. The directions do say:
If is odd, print Weird
If is even and in the inclusive range of 2 to 5, print Not Weird
If is even and in the inclusive range of 6 to 20, print Weird
If is even and greater than 20, print Not Weird
As a programmer, you do not have to follow the given directions. You need to formulate a solution that results in an algorithm that meets the specifications. Part of the art of programming is to recognize whether the specs are subject to change, anticipate needs for updates, and even correct some assumptions that the specs make that might be in error. So while this is a simple task, it is rich in teaching. (Kudo's to your instructor).
One way to look at the specs is that it implies non-negative inputs. What is one to do with -4 or 0? Not in the specs. It is fair to look at proposed input and see what it is so you can handle that case. Sometimes other logic is added to reject illegal entries. It isn't specified here, so I would handle it with a comment in the code that input is expected to be a positive non-zero integer.
In addition, there is a certain approach that is a bit more wholistic: If odd print Weird and quit, otherwise you know num is even, so further checking is not needed for evenness. So then you print Weird for num in the range [6..20], otherwise print Not Weird. The big picture is odds print Weird, any number [6..20] prints Weird, everything else prints Not Weird.
if num % 2 == 1 : # Handle odd num
print("Weird") # Any odd prints Weird
else: # Handle even num
if 6 <= num <= 20:
print("Weird")
else:
print("Not Weird")
The point is once you do a test you know womething that can be carried forward in your code. Once you test that something is odd, handle it, and after that the code knows the number if not odd is even, and you don't have to keep testing it. Logically, if odd print and be done. Otherwise (num is even) print "Weird" for num in [6..20], print "Not Weird" otherwise. Rather than 3 tests when a number is even now there is just the one test for num being in the range [6..20].
A few comments are sprinkled in. No testing for input less than 1.
The whole thing could be simplified further
if num % 2 == 1 or 6 <= num <= 20: print("Weird")
else:print("Not Weird")
That does simplify the whole thing.
It is interesting that in programming the simple question of "what is wrong with my statement" can sometimes be addressed with "should I be using this approach?" I've gone far afield with this answer. Originally, what's with my if statement was the issue, but this little gem of a problem is really teaching a lot. (Again, Kudo's to the teacher!)
So, do you transform thw whole question and use an or, or does the first approach work better. In the real world you might have a sense of how the specification may be changed and your solution will be best when it is correct, uses reasonable resources, and is maintainable.
I'm relatively new to Python and I decided to try and code a relatively simple collatz conjecture where the user enters a number (integer). The code is just a simple function that calls itself. i is a list that should have every number that the function calculates appended to it. I'm new to executing Python scripts and I have tried using the IDLE shell to run the code. It asks me what number I want but when I enter a number nothing is printed? I'm sure I just need to edit a small bit of this code (or maybe it's all wrong yikes) but does anybody have any idea why my script returns nothing? Sorry about this and thanks.
Here's the code:
l = input("Enter a number: ")
l = int(l)
i = []
def collatz(n):
if n==1:
return i
if n%2 == 0:
n = n/2
i.append(n)
return collatz(n)
else:
n = ((n*3) + 1) / 2
i.append(n)
return collatz(n)
print(i)
collatz(l)
There are three returns before your print and one of them is inside an else statement, which means that at least one of them will be executed, so your print won't even be reached to be executed, you should move it right after the function definition to see something:
def collatz(n):
print(i) # <= print here
if n==1:
....
See more about the return statement. A snippet:
return leaves the current function call with the expression list (or None) as return value.
As others have mentioned, all of the execution paths in your function end in a return statement, so that print call is unreachable. So if you want each value of n or i to be printed you need to move the call to somewhere that it will be reachable. ;)
Also, there's a little bit of redundancy in that code. You don't need
i.append(n)
return collatz(n)
in both the if and else branches, you can move them outside the if...else block.
Here's a modified version of your code. I've also changed the / operators to // so that the results of the divisions will be integers.
i = []
def collatz(n):
print(n)
if n==1:
return i
if n%2 == 0:
n = n // 2
else:
n = ((n*3) + 1) // 2
i.append(n)
return collatz(n)
# Test
print(collatz(12))
output
12
6
3
5
8
4
2
1
[6, 3, 5, 8, 4, 2, 1]
I am trying to create a simple program to apply the statement of the Collatz Conjecture to an integer that the user can enter, I have:
def collatz(n):
print n,
if n % 2 ==0:
n = n / 2
elif n == 0:
Print "Collatz Conjecture true for" , 'n'
else:
n = n *3 + 1
input("\n\nInsert a positive integer:")
def collatz(n)
However it is saying there is a syntax error in the line:
Print "Collatz Conjecture true for" , 'n'
I can't see what mistake ther is in this line.
Also as I haven't been able to test it yet, does this look as though it will work ok?
Python is case sensitive. Use "print" not "Print".
Well, your syntax error is that python is case-sensitive, so you need print rather than Print.
But you've got more problems:
'n' prints the string n. I think what you want is n to print the value of the variable (or if not, then you can just make a single string "... true for n").
Finally (I think), in order to run the function collatz, you don't need the def; that's just for the definition.
More problems:
The stopping condition should be n == 1, not n == 0.
You have to recur or iterate, as is you're only making one step.
Check the input, make sure it really is a positive number.
def collatz_steps(n):
steps=0
if n==1:
return 0
else:
while n!=1:
if n%2==0:
n=n/2
steps+=1
else:
n = 3*n+1
steps+=1
return steps
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Simple Prime Generator in Python
First I will prompt user to input any number. Then my code will check whether does the number input by the user is a Prime number not.
Here is my codes:
num = int(raw_input("Input any of the number you like:"))
for x in range(2, int(num**0.5)+1):
if num % x == 0:
print "It is not a prime number"
else:
print "It is a prime number"
But question is I cant seem to get the output for 2 and 3. And when I randomly input any numbers like 134245, the system will output alot of sentences. And I do not know why?
Appreciate any kind souls to help me up :)
import urllib
tmpl = 'http://www.wolframalpha.com/input/?i=is+%d+a+prime+number'
def is_prime(n):
return ('is a prime number' in urllib.urlopen(tmpl % (n,)).read())
you should stop once num % x == 0 is true (no need for further testing) and print 'it is a prime number' only if the loop completed without anything printed before.
A number is prime if it only divides by 1 and itself. A pseudocode follows:
boolean prime = true;
for (int i = 2; i * i <= num; i++)
if (num % i == 0) {
prime = false;
break;
}
if (prime)
println("It is prime!");
else
println("It is not prime!");
Look at your code like this:
num = ...
for x in range(2, int(num**0.5)+1):
print something
The body of the loop is executed at every iteration. That means you're printing something at every iteration, i.e. for each x that you check to see if it's a factor of num, you print. That's not what you should be doing; in order to determine whether a number is prime, you check all possible factors first, then print your result. So you shouldn't be printing anything until after the loop.
But question is I cant seem to get the output for 2 and 3.
You're looping from 2 to ceil(sqrt(n)). For 2 and 3, this is an empty range, hence no iteration happens. Either special-case it or rewrite the code such that it assumes that n is prime and tries to disprove it in the loop.
the system will output alot of sentences.
You're printing on every iteration. Instead, use a boolean flag (or a premature return, if you factor it out into a function) to determine prime-ness and print once, after the loop, based on that prime.
Your code is not structured well-- the algorithm continues to loop all the way up to the top of your range, even if you already know that the number is composite, and it also prints some result on each iteration when it should not.
You could put the logic into a function and return True or False for prime-ness. Then you could just check the result of the function in your if statement.
def is_prime(num):
for x in range(2, int(num**0.5)+1):
if num % x == 0:
return False
return True
num = int(raw_input("Input any of the number you like:"))
if not is_prime(num):
print "It is not a prime number"
else:
print "It is a prime number"
Here are two Python routines for calculating primes. (Hint: Google for Sieve of Eratosthenese):
def pythonicSieve(maxValue):
"""
A Pythonic Sieve of Eratosthenes - this one seems to run slower than the other.
see http://love-python.blogspot.com/2008/02/find-prime-number-upto-100-nums-range2.html
"""
return [x for x in range(2,maxValue) if not [t for t in range(2,x) if not x%t]]
def sieveOfEratosthenes(maxValue):
"""
see http://hobershort.wordpress.com/2008/04/15/sieve-of-eratosthenes-in-python/
"""
primes = range(2, maxValue+1)
for n in primes:
p = 2
while n*p <= primes[-1]:
if n*p in primes:
primes.remove(n*p)
p += 1
return primes