2

I have to find out whether number(N) is a prime or not using recursion, no loops are allowed. I've tried converting the usual code that uses a for loop to a recursive one, but it's not behaving the same. This function is included in another function, which is part of another function. only parameters a and N should be used and passed Here is my function.

a=2
def is_prime(a,N):
prime = True
if N <=1:
    return 
else:
    if a >= N:
        return 
    else:
        if N == 2: 
            prime = True
            print(N)
            return 
        elif (N % a) == 0:
            prime = False
            return is_prime(a+1,N)
        else:
            prime = True
            print(N)

return

I believe the bug is somewhere here.

elif (N % a) == 0:
            prime = False
            return is_prime(a+1,N)
        else:
            prime = True
            print(N)

Here is the code I tried to convert.

if num > 1:
   for i in range(2,num):
      if (num % i) == 0:
         print(num,"is not a prime number")
         print(i,"times",num//i,"is",num)
         break
   else:
      print(num,"is a prime number")

else:
   print(num,"is not a prime number")
Amiel Moodley
  • 43
  • 1
  • 1
  • 7
  • 1
    Possible duplicate of [Sieve of Eratosthenes - Finding Primes Python](http://stackoverflow.com/questions/3939660/sieve-of-eratosthenes-finding-primes-python) – hd1 May 08 '16 at 02:14
  • Is the function supposed to return anything? – niemmi May 08 '16 at 02:20
  • 3
    @hd1, I disagree on the duplicate call. This specifically asks for a solution using recursion without any loops. That solution clearly uses loops. – Alex Huszagh May 08 '16 at 02:23
  • nope, it's just meant to print(N) if it's prime. this function is part of another function. @niemmi – Amiel Moodley May 08 '16 at 02:25

7 Answers7

4

Your solution is close, with just a few changes needed to make it work.

def is_prime(a,N):
    print(a, N)
    if N <= 1:
        return 
    else:
        if a >= N:
            print(N)
        else:
            if N == 2: 
                print(N)
            elif (N % a) == 0:
                return False
            else:
                return is_prime(a+1,N)

    return False

You didn't give any examples of calling this function, but I assume it's always called with a being 2, since any other value wouldn't make sense. So if you run the above function like so, you should get the right output:

print(is_prime(2, 7))  => True
print(is_prime(2, 4))  => False
print(is_prime(2, 37)) => True

I think you have a misunderstanding of how recursion works, you're assigning this prime variable in the body of the function, but never doing anything with it. Maybe your confusion comes from a misunderstanding of scopes in Python. That prime variable will not be 'shared' across invocations, it will just create a new prime every time.

EDIT: Didn't realize you wanted the function to just print out the prime if it's a prime, changed the code accordingly.

Marcus Buffett
  • 1,289
  • 1
  • 14
  • 32
2
def prime(n,j):
    if(n<2):
        return False
    if(j==n):
        return True
    if(n%j==0):
        return False
    return prime(n,j+1)

print(prime(n,2))

A number is called prime if it is only divisible by itself and 1. So iterate from 2 to n-1, if n is divisible by any of (2,3,4,..n-1) return False.
If j == n then there is no such number from (2,3,4...n-1) divisible by n, Hence it's Prime.

Suraj Rao
  • 29,388
  • 11
  • 94
  • 103
1

Your function sometimes returns something and sometimes returns nothing -- it should be either all one or the other, not both. In this case is_prime() looks like a boolean function so it should return True or False. We'll leave the printing to the caller:

def is_prime(N, a=3):

    if N == 2:  # special case
        prime = True
    elif N <= 1 or N % 2 == 0:  # too small or even
        prime = False
    elif a * a > N:  # tried all divisors to sqrt, must be prime
        prime = True
    elif (N % a) == 0:  # divides evenly, not a prime
        prime = False
    else:  # can't tell yet, recursively try the next (odd) divisor
        prime = is_prime(N, a+2)

    return prime

for x in range(100):
    if is_prime(x):
        print(x)

Keep it simple. Think through each possible case. Avoid increasing the indention depth unnecessarily, it makes your code more complicated.

The above solution tries to speed up prime detection by avoiding even numbers (both divisor and number) and limiting the divisor to the square root of the number. This can matter as without these optimizations, a recursive solution will likely run out of call stack space at around N=1,000 whereas the above should go to N=1,000,000 without expanding the call stack.

cdlane
  • 40,441
  • 5
  • 32
  • 81
0

Since the goal is to print the number in case it's prime let's do that part first. You've already got a condition for it in your code but there was no print:

if a >= N:
    print(N)
    return

Next we need to handle all the cases where N > 1:

if N == 2: 
    prime = True
    print(N)
    return 
elif (N % a) == 0:
    prime = False
    return is_prime(a+1,N)
else:
    prime = True
    print(N)

First check, if N == 2 is unnecessary since there's already a block before that handles all the cases where N is prime so it can be removed. That said having it there doesn't cause any harm.

The next block that checks if N is divisible by a should terminate the recursion. Since you know that N isn't prime you should just stop there.

Final block that gets executed when N is not divisible by a should do the recursion instead. As it stands now the recursion stops as soon as N % a != 0 which is clearly wrong.

Here's a working sample with above modifications and cleanup:

def is_prime(N, a=2):
    if N <= 1:
        return
    elif a >= N:
        print(N)
    elif N % a != 0:
        is_prime(N, a + 1)
niemmi
  • 17,113
  • 7
  • 35
  • 42
0

to print the list of prime numbers between a given range

l=[]
def primenum(x,y):
    global l
    if x==y:
        print(l)
    else:
        m=0
        for i in range(1,x+1):   
            if x%i==0:
                m+=1
        if m==2 or x==1:
            l+=[x,]
            return primenum(x+1,y)
        else:
            primenum(x+1,y)
0
def is_prime(n):
  def prime_helper(n, x):
    if n == 1:
      return False
    elif n % x == 0:
      return False
    else:
      return prime_helper(n , x+1) if x * x <= n else True 
  return prime_helper(n, 2)

if you don't want to use a helper function

def is_prime(n, x=2):
    if n == 1:
      return False
    elif n % x == 0:
      return False
    else:
      return is_prime(n , x+1) if x * x <= n else True 

Also, you don't need to check all the numbers between (1 - N) but only up to sqrt(n). You can change your iterative approach to

for loop

from math import sqrt 
def is_prime(n):
  if n == 1:
     return False
  for i in range(2, round(sqrt(n)) + 1):
     if n % i == 0:
        return False
  return True

while loop

def is_prime(n):
  if n == 1:
    return False
  i = 2
  while i * i <= n:
     if n % i == 0:
        return False
     i += 1
  return True
0

Since there are so many cool attempts to improve the code, I gave it a try and here's my best solution to any case of finding if a number is prime using recursion. You'll have to add the print statements or any other logics yourself, but the main idea is quite simple:

def is_prime_recursive(n, checkpoint = 2):
if n in [1, checkpoint]:
    return True
if n % checkpoint == 0:
    return False
return is_prime_recursive(n, checkpoint + 1)
  • The function should be called with one parameter only - the number to check - , as it sets number two as the first checkpoint;
  • If the number is one or the current checkpoint (in the first case, one or two) then it's a prime;
  • If the number is divisible by the current checkpoint, return false, because it's not a prime;
  • If the number doesn't fall into any of the previous cases, call the function again but this time increase the checkpoint by one;

This is repeated until the number falls into one of the cases - being the worst case the number is a prime: first case (n == checkpoint)

unamednada
  • 57
  • 3