What’s wrong with my recursion for finding primes? (Python) - python

I’m trying to create a program that lists all the primes below an inputted number, and I came up with the code:
def primes():
num = 20
numlist = list(range(1,num+1))
i = len(numlist)
for j in numlist[2:]:
ans = divisible(j,i)
if ans:
numlist.remove(j)
print(numlist)
def divisible(m,n):
if m!=n and m%n==0:
return True
elif n == 1:
return False
else:
divisible(m, n-1)
primes()
(I used an in-browser IDE so the num part was a proxy for the input.)
My idea was to create a separate function divisible() that when inputted two ints, m and n, would check if n divides m. I'm not sure if I was right in my recursion, but I wrote divisible(m,n-1) the idea was that it would iterate through all the integers from n downward and it would return True if any n divided m, or False if it reached 1.
In the main code, m iterated through all the numbers in a list, and n is the total number of elements in the same list. I put the print(numlist) inside the if statement as an error check. The problem I’m having is nothing is printing. The code returned literally nothing. Is there something I’ve missed in how recursion works here?

There's a lot wrong here:
You've made a common beginner's recursion error in that you have a recursive function that returns a value, but when you call it recursively, you ignore the returned value. You need to deal with it or pass it along.
It seems like this modulus is backward:
if ... and m%n==0:
Maybe it should be:
if ... and n % m == 0:
You're code doesn't appear to be calculating primes. It's looks like it's calculating relative primes to n.
You start your list of numbers at 1:
numlist = list(range(1,num+1))
But you start testing at index 2:
for j in numlist[2:]:
Which is the number 3 and you never check the divisibility of the number 2.
Even with all these fixes, I don't feel your algorithm will work.

Your divisible function doesn't return anything if it falls into else part. change it as
def divisible(m, n):
if m!=m and m%n==0:
return True
elif n==1 :
return False
else:
return divisible(m,n-1)
This should work

Related

I'm trying to code a function that finds prime numbers. Some of the "for" loops that I included in the code don't seem to be working

I have been learning how to code with Python for more or less two or three weeks and I came across an exercise that required me to find the number of primes numbers that exist up to a given number. If anyone could help that would be great.
My code seems to be working for the first few prime numbers (it excludes from the list created 4 and 6) but then it stops.
I am new to coding, so this could be wrong, but I think that for some reason one, or even both, of the "for" loops stopped working.
This is my code:
def count_primes(num):
primes = [2, 3]
for i in range(4,num+1):
cond = True
for x in range(0,len(primes)-1):
if i%primes[x] == 0:
cond = False
elif i%primes[x] > 0:
cond = True
if cond == True:
primes.append(i)
pass
print(primes)
return len(primes)
count_primes(100)

Understanding recursion in Python with if case

In solving this codewars challenge I came across a recursion example I don't understand.
The challenge is to give the next nth numbers, given an initial 3 number seed sequence, where the nth numbers are determined by adding the last three numbers of the sequence.
So for the seed sequence list of [1,2,3] and given n=5, you'd return the following:
1 + 2 + 3 = 6
2 + 3 + 6 = 11
Answer:
[1, 2, 3, 6, 11]
I solved the problem with the following:
def tribonacci(sequence,n):
if n <=3:
return sequence[:n]
else:
for i in range(n-3):
sequence.append(sum(signature[-3:]))
return sequence
In reviewing the other solutions, I came across this very elegant solution that uses recursion:
def tribonacci(sequence,n):
return sequence[:n] if n<=len(sequence) else tribonacci(sequence + [sum(sequence[-3:])],n)
My question is: why doesn't this just run infinitely? I'm having trouble understanding why this terminates with the nth iteration. It doesn't seem like the function of 'n' is stipulated anywhere, except in the if case.
As an experiment, I modified the code to ignore the less-than-or-equal-to-length-of-sequence case, like so:
def tribonacci(sequence,n):
return tribonacci(sequence + [sum(sequence[-3:])],n)
And this does run infinitely and errors out with a runtime error of max recursion depth.
So obviously the case option is what seems to control the termination, but I can't see why. I've used recursion myself in solves (for instance in creating a factoring function), but in that example you subtract n-1 as you iterate so there's a terminating process. I don't see that happening here.
I guess I don't completely understand how the return function works. I was reading it as:
return n-item list if n is less/equal to sequence length
else
rerun the function
Perhaps I should actually be reading it as:
return n-item list if n is less/equal to sequence length
else
return n-item list after iterating through the function enough times
to fill a n-item list
At each level of recursion, the sequence becomes longer because of concatenation (+). Eventually it will become long enough for n to become less than length.
You can rewrite this:
a = b if p else c
as this:
if p:
a = b
else:
a = c
Knowing that, you can see that this:
def tribonacci(sequence,n):
return sequence[:n] if n<=len(sequence) else tribonacci(sequence + [sum(sequence[-3:])],n)
is the same as:
def tribonacci(sequence,n):
if n <= len(sequence):
return sequence[:n]
else:
return tribonacci(sequence + [sum(sequence[-3:])],n)
Now you should be able to see that there's a condition controlling that the recursion doesn't go on for ever.

Getting First Prime in a List of Random Numbers

I was playing around with the Python shell and I have what I believe is an extremely naive implementation of a function that simply returns the first prime number in a list of 100 randomly generated numbers (whose values are between 0 and 99, inclusive). Code below:
>>> def is_prime(n):
if n < 2:
return False
elif n == 2:
return True
for i in range(2, n):
if n % i == 0:
return False
return True
>>> from random import randint
>>> numbers = []
>>> for i in range(0, 100):
numbers.append(randint(0, 99))
>>> def get_first_prime(values):
temp = []
for i in values:
if is_prime(i):
temp.append(i)
return temp[0]
>>> get_first_prime(numbers)
I want this function to strictly return only the first prime number. My implementation uses a helper list to cache all primes and then simply return the element at the first index. It works, but I'm not convinced it's a good one. I'm sure there is a more efficient way of doing this that does not require scanning through the entire list, but I can't seem to think of one yet.
What are some better alternatives?
def get_first_prime(values):
for i in values:
if is_prime(i):
return i
This way you don't keep searching once you find a prime. The function implicitly returns None if no prime is found.
Yes, you do not even need to generate a list of all the random numbers, you can test each one as they are generated, and return as soon as you've found one.
from random import randint
import math
def is_prime(n):
if n < 2:
return False
elif n == 2:
return True
for i in range(2, int(math.sqrt(n) + 1)):
if n % i == 0:
return False
return True
def get_first_prime(number):
for i in range(number + 1):
n = randint(0, 99)
if is_prime(n):
return n
get_first_prime(100)
You are right. Your code not only has more time complexity (running through all the list elements even after finding the first prime) and space complexity (temp list to hold all the primes) but also stands a risk of throwing IndexError when there are no prime numbers in the list.
So you could mend it in the following manner:
def get_first_prime(values):
for i in values:
if is_prime(i):
return i
Note that when there is no prime in the input the return statement would never get executed that means there is no explicit return; in which case Python returns None. So, if you choose to, you can return the value of your choice at the end of the function outside for loop to indicate 'not found'.
def get_first_prime(values):
for i in values:
if is_prime(i):
return i
return -1
Pythonic way of dealing with this is to raise an Exception and let the caller of the function deal with the exception.
prime = next(filter(isprime, numbers))
See find first element in a sequence that matches a predicate.

How to write more Pythonic Code

I started learning python today from the tutorial on the official site.
When reading about filter(function, sequence) i thought of making a function that returns if a number is prime to use it with the filter.
notDividedBy = [2,3,4,5,6,7,8,9]
def prime(num):
"""True if num is prime, false otherwise"""
copy = notDividedBy[:]
check = True
if num in copy:
copy.remove(num)
for x in copy:
if num % x == 0:
check = False
break
return check
The above code works in the shell.
My question is: Since i feel like although a solution, it is not the most elegant one, can anyone transform this code to something more python-like?(better structure? less lines?)
I believe it would help me for better understanding of the basics of the language.
The thing is, don't use any imports or anything, just simple staff.
Creating many many copies of lists is not a particularly efficient way of doing things. Instead use the xrange() (Python 2.x) or range() (Python 3) iterator. Here's one (naive) way you could implement a primality test:
from math import sqrt
def isPrime(n):
if n < 2: return False
if n == 2: return True
if not n % 2: return False #test if n is even
#we've already remove all the even numbers, no need to test for 2
#we only need to test up to sqrt(n), because any composite numbers can be
# factored into 2 values, at least one of which is < sqrt(n)
for i in xrange(3, int(sqrt(n)) + 1, 2):
if not n % i:
return False
return True
How about this one:
def is_prime(num):
return not any(num%i == 0 for i in xrange(2,num/2+1))
for i in xrange(10):
print i, is_prime(i)
Explanation
start with:
(num%i==0 for i in xrange(2,num/2+1))
This is a generator expression. I could have made it a list comprehension:
[num%i==0 for i in xrange(2,num/2+1)]
The list comprehension is equivalent to:
ll=[]
for i in xrange(2,num/2+1):
ll.append(num%i==0)
The difference between the generator and the list comprehension is that the generator only gives up it's elements as you iterate over it -- whereas the list comprehension calculates all the values up front. Anyway, from the above code, you can see that the expression generates a sequence of True's and False's. True if the number can be divided by i and False otherwise. If we generate a sequence of all False numbers, we know we have a prime.
The next trick is the any built in function. It basically searches through an iterable and checks if any of the values is True. As soon as it hits a True, it returns True. If it gets to the end of the iterable, it returns False. So, if the entire sequence is False (a prime number) then any will return False, otherwise it returns True. This would be perfect for a not_prime function, but our function is is_prime, so we just need to invert that result using the not operator.
The benefit of using the generator expression is that it is nice and concise, but also that it allows any to return before checking every value which means that as soon as it finds a number that divides num, it returns instead of generating all num/2 numbers.
Anyway, I hope this explanation is helpful. If not, feel free to leave a comment and I'll try to explain better.
One thing off the bat, if you are going to implement prime testing in this fashion, there's no reason to use an auxillary array
def prime(num):
"""True if num is prime, false otherwise"""
check = True
#if num in copy:
# copy.remove(num)
for x in range(2,x-1):
if num % x == 0:
check = False
break
return check
Here's a 2 liner using filter().
def prime(num):
"""True if num is prime, false otherwise"""
if num < 2:
return False
return len(filter(lambda x: num % x == 0, range(2, num))) == 0

Python Prime "C-number"

"C-number" is an integer n > 1 such that (b^n)mod n = b for all integers 1
Basically I have to create a program to run through about 2000 integers(1-2000), and have it satisfy the C-number condition, and then also check to see if it is NOT a prime number. I can't seem to get the loop working correctly.
I have a program that creates a list of non primes, and a working program that if I input a number, it will return me that number if it is a c-number, if not I'll get false returned.
I want it to just check numbers 1-2000 rather than just the one number I inputted, and then also check against the list of non prime numbers.
Here's my code:
import numpy
def primesfrom2to(n):
""" Input n>=6, Returns a array of primes, 2 <= p < n """
sieve = numpy.ones(n/3 + (n%6==2), dtype=numpy.bool)
for i in xrange(1,int(n**0.5)/3+1):
if sieve[i]:
k=3*i+1|1
sieve[ k*k/3 ::2*k] = False
sieve[k*(k-2*(i&1)+4)/3::2*k] = False
return numpy.r_[2,3,((3*numpy.nonzero(sieve)[0][1:]+1)|1)]
num=range(600)
mylist =primesfrom2to(600)
s = [item for item in num if item not in mylist]
a=[]
d=[]
from math import *
def numc(n):
for a in range(1,n):
c= a**n
d=c%n
if a == d:
return n
else:
return False
print numc(561)
You probably need to just fix the indentation (needs fixing in a lot of places):
def numc(n):
for a in range(1,n):
c= a**n
d=c%n
Python is pretty much written through indentation.
The easiest and even more important: cleanest way is to create two lists, one for prime numbers you found and one for c numbers. Then go through the lists to check which ones are in c numbers and not in prime numbers. Also split the functions for prime and c number in two functions. Something like:
prime_numbers = []
c_numbers = []
amount = 2000
for i in xrange(amount):
if is_prime(i):
prime_numbers.append(i)
if is_c_number(i):
c_numbers.append(i)
for i in xrange(amount):
if i in c_numbers and (not i in prime_numbers):
print i
First, not sure numc() does what you expect -- as written, that if statement will be tested only for the last value of a in the range. The if statement is not in the for loop block, so the loop will spin through the assignments, and the if statement only goes against the values assigned in the last iteration. This seems more what you're looking for:
def numc(n):
for a in range(1,n):
c= a**n
d=c%n
if a != d:
return False
return n
Here if some a value fails the if test, the function returns False. If all a values pass it returns true.
Second, neither my draft nor yours returns an array, just an integer or a boolean. To get an array of values passing, you have to call the function on each item of an array of candidates.
This gives you the output, integer or boolean, for each member of the candidate array:
c_values = [numc(i) for i in range(1, 2000)]
You can get just the passing values by testing in the loop:
c_values = [numc(i) for i in range(1, 2000) if numc(i)]
You can do so without calling numc() twice by nesting the list comprehensions:
c_values = [i for i in [numc(j) for j in range(1, 2000)] if i]
That first generates the complete array of output values, then returns only those that are True.
EDIT: You seem confused by the block indentation, or perhaps the two return statements. Here is another way with one return:
def numc(n):
retval = n
for a in range(1,n):
c= a**n
d=c%n
if a != d:
retval = False # reset return value
break # halt the loop
return retval
Here the default return value is << n >>, to be reset within the << for >>loop if cnumber conditionality is violated by some value of << a >>. In which case, << break >> halts the loop (though here it needn't.) The function just returns whatever << retval >> happens to be when the return statment is reached.
My initial draft had the same effect, but there the for loop was interrupted / 'broken' by the << return False >> statement -- which also there interrupted the function, preventing it from reaching the << return n >>. If that statement weren't reached, ie no << a >> violated conditionality, the function would reach and execute << return n >>. If a function has two return statements, it will only execute the first one reached, and all code after that will be ignored.

Categories