Prime numbers using generators in Python? [duplicate] - python

This question already has answers here:
Simple prime number generator in Python
(27 answers)
Closed 6 years ago.
I wrote this simple python function to calc:
def isPrime(number):
if number == 2:
return True
elif number > 1 and number % 2 != 0:
for current in range(3, number):
if number % current == 0:
return False
return True
And I'm calling it to print out the sum of all prime numbers from 1 to 2 million, as in project euler #10
However it's terribly slow, and I was wondering if I could tackle the same problem using generators? But I don't really understand generators in python completely..
Any help on how to solve this problem more efficiently would be appreciated! Thanks :)

Firstly, I suggest you use a better function to check whether a number is prime or not.
Here's a better modification, from https://jeffknupp.com/blog/2013/04/07/improve-your-python-yield-and-generators-explained/ which is an excellent
explanation on generators in Python.
import math
def is_prime(number):
while True:
if number == 2:
return True
elif number > 1 and number % 2 != 0:
for current in range(3, int(math.sqrt(number) + 1), 2):
if number % current == 0:
return False
return True
return False
Secondly, you need to understand what a Generator actually does. Again Jeff Knupp explains it perfectly.
In short a generator is a function that does not "return" it simply "yields" and takes back control when the next() method is called on it.
So no variables that are created during the function are lost, and memory is saved by not creating the variables defined in the function again and again.
Then you can go on solving Euler 10, which is also explained in the link. :)
Good luck with the rest of the Eulers!

Another angle of attack on this problem is to try a different algorithm rather than attempting to optimize your current method. Learning more about generators is great, but you could also try solving this using a sieve, which can be quite efficient.
The general idea would be to "mark" all composite numbers (not prime), leaving behind the primes. It's pretty efficient, as my python implementation runs in ~3.5s

Related

Validating given input and printing every prime number =< given input. (Python)

So I have read tons of solutions to this type of questions, but they all seem to be way too complicated, or I can't find any useful solutions in them.
I have written the first part where I have to ask for an input and validate it to be an integer, but I can't figure out how to write the code for the second part. Efficiency isn't a necessity here, but I think it's better if I learn the most efficient way from the get go. From what I read, using the radicle of the input and checking the divisors is the way to go here, but as I said, I can't figure out how to actually write the code and integrate it into what I already have.
while True:
x = str(input("Please enter an integer: "))
try:
x = int(x)
except ValueError:
print("Please enter a valid integer: ")
continue
break
Any help is greatly appreciated!
It is better to edit multi-line code into your question, rather than post a comment, because then you are not limited to a single line.
Your code appears to be:
def is_prime2(n):
if n == 2 or n == 3:
return True
#endif
if n % 2 == 0 or n < 2:
return False
#endif
for i in range(3, int(n**0.5)+1, 2):
if n % i == 0:
return False
#endif
#endfor
return True
#enddef
print(n)
I have added comments to indicate where I think that various statements end. I may have mistaken the indentation converting from a single line.
Apart from that print(n), which is either not part of the function definition or comes after a return, this appears to work correctly. It will be too slow for very large values of n though it will be fine for smaller values and for testing. For very large values have a look at the Sieve of Eratosthenes.
Write an isPrime(n) function that returns true if n is prime, false otherwise. Then test all the numbers from 2 up to the entered integer to see if they are prime.
We will help you to improve your code, but you have to write it first.

Why is recursion not ending with the correct value? [duplicate]

This question already has an answer here:
Why Python recursive function returns None [duplicate]
(1 answer)
Closed 2 years ago.
I am trying to write a code to calculate GCD of two numbers(n and m) recursively. I want my answer to update in gcd_val as the recursion progresses. I tried debugging and can't understand why it chooses the earlier gcd_val as compared to the value obtained in its sub-call(inner recursive call). I want to know why is this happening and what should be the correct way to do it? I get the answer 2 when it should be 4.
def find_gcd(n, m, gcd_val):
factor_list = [2, 3, 5]
if n == 0 or m == 0:
return 0
for f in factor_list:
if n % f == 0 and m % f == 0:
find_gcd(int(n/f), int(m/f), gcd_val)
gcd_val *= f
return gcd_val
print(find_gcd(20, 8, 1))
Almost all programming languages defaults to pass arguments by value. That is the second the function starts up the arguments are unique memory locations for just that round and all alterations done with it will never affect a prevous call even if it is the same name.
Programming languages doesn't discriminate between self calling or caling something else so when find_gcd calls find_gcd it treats it the same as if it called find_gcd2 with a similar implementation.
Just like you use print you actually need to use the returned value or else the recursive call in find_gcd is dead code.

RecursionError in Project Euler #5

I'm receiving a "maximum recursion depth exceeded" error when executing my program to solve this problem. Project Euler's question #5 asks to find:
The smallest positive number that is evenly divisible by all of the numbers from 1 to 10.
I've tried to write a program that recursively checks if x is divisible by each integer 1-10, and if it doesn't then we call it again with x incremented by 1 and repeat until x is found. (In this case the answer is 2520, which is why I added the if statement.)
def euler5(x):
if x < 2521:
for i in range(1, 11):
if x % i == 0:
print(x)
else:
euler5(x+1)
else:
print(x)
x = 2
print(euler5(x))
The reason for this is that Python (or CPython, at least) has a limited stack size and no tail call optimization. So you cannot use unbounded recursion in Python, unlike Scheme (for example).
The solution is to use a regular loop:
x = 0
while True:
x += 1
# Put loop body here
In you defined function, you could you a loop even if you do not know math functions. However, your code is not efficient as program has to keep checking the values to see if it matches the condition. Recursion is not recommended as it should be flexible to be used with other values not just for this question. Euler questions are meant to train your coding practices.
A better method can be used to simplify your code:
from functools import reduce
from fractions import gcd
def lcm(a,b):
return a*b//gcd(a,b) #gcd is greatest common divisor AKA HCF
print (reduce(lcm, range(1, 20+1)))

Python: determining if a number is prime [duplicate]

This question already has answers here:
How to create the most compact mapping n → isprime(n) up to a limit N?
(29 answers)
Closed 7 years ago.
I am new to Python and I'm attempting to write a code that checks to see whether or not a number is prime. So far, I've written this:
def main():
n = input("Enter number:")
isprime(n)
def isprime():
x = Prime
for m in range (1,n+1,1)
result = n % m
print result
main()
I'm not sure how to proceed after this. I know I have to define isprime. Any help would be greatly appreciated. Thank you!
Your first and biggest problem is that you need to list n as a parameter to isprime before you can use it within isprime, and before you can pass an argument in main. See the tutorial on Defining Functions for more details. But basically, it's like this:
def isprime(n):
Also, that x = Prime is going to raise a NameError, because there's nothing named Prime. Given that it doesn't actually do anything at all, you should just delete it.
Of course that won't make this a complete working prime testing function, but it is how to proceed from where you are.
The next step is to consider what to return from the function. If you find a value that divides n, then obviously n isn't prime, and therefore isprime is false. If you go through all possibilities and don't find anything that divides n, then isprime is true. So, with two return statements in the right places, you can finish the function.
Once it's at least always returning True or False, you have bugs to fix.*
Look at what numbers you get from range(1, n+1, 1). Two of those numbers are guaranteed to divide any n. How do you avoid that problem?
After you've got it working, then you can work on optimizing it. If you look up primality test on Wikipedia, you can see a really simple way to improve the naive trial division test. A bit of research will show the pros and cons of different algorithms. But if what you've got is fast enough for your purposes, it's usually not worth putting more effort into optimizing.
* You might want to consider writing a test program that calls isprime on a bunch of numbers and compares the results with the right answers (for answers you already know off the top of your head—1 is not prime, 2 is prime, 17 is prime, etc.). This is called Test Driven Development, and it's a great way to make sure you've covered all the possible cases—including outliers like 0, 1, 2, -3, etc.
Your isprime is quite close. The first line x = Prime is unnecessary, so let's get rid of that.
Now, let's take a look at what you're doing next:
You seem to want to check if there are any numbers that divide n perfectly. While this is the correct approach, you are including n and 1 in the numbers that you are testing. This is wrong for obvious reasons.
There is another error: you use n without ever defining it (I think you want it to be a parameter to your function). So let's put all this together:
def isprime(n):
for m in range(2, n):
if not n%m: # m divides n perfectly
return False
return True # if n were not prime, the function would have already returned
But going a step further, you don't really have to check every number between 2 and n-1. You just need to check the numbers between 2 and the square-root of n:
def isprime(n):
for m in range(2, int(n**0.5)+1):
if not n%m:
return False
return True

Python prime numbers generator yield vs return [duplicate]

This question already has answers here:
Fastest way to list all primes below N
(39 answers)
Closed 9 years ago.
Searching for python prime numbers generator, I found:
def primes(n):
if n==2: return [2]
elif n<2: return []
s=range(3,n+1,2)
mroot = n ** 0.5
half=(n+1)/2-1
i=0
m=3
while m <= mroot:
if s[i]:
j=(m*m-3)/2
s[j]=0
while j<half:
s[j]=0
j+=m
i=i+1
m=2*i+3
return [2]+[x for x in s if x]
print primes(13)
print primes(3000)
and also:
def get_primes(number):
while True:
if is_prime(number): #is_prime is defined somewhere else
yield number
number += 1
What's more efficient, return a list or the yield command? Why? Consider I'm looking for a very large amount of primes numbers, like first 1000 primes. By the way, the second code seems to be an infinite loop, how to stop it?
Thanks and sorry for so many questions.
It really depends on what you want to do with the list of primes.
First off, as Martijn pointed out, the first algorithm is a pretty clever prime sieve, and the second tests every prime number. If you're interested in fast prime number algorithms, I would look up a few different prime sieves to try to better understand the approach. The simplest is the Sieve of Eratosthenes.
Anyway, I don't think that was your question. You're really looking for the difference between a normal Python function and a generator. There are a lot of questions on SO and plenty of documentation that give a good explanation of what a generator is.
This showed up in the sidebar when I was looking at your question, and I imagine that it would be helpful. Or just search the docs for "generator".
The quick explanation is that your first function returns a list of primes up to n. Once you have that list, you can access any member of it when you want, call a function on the whole list, etc. The second approach is a generator. It doesn't return a list -- this returns an iterator that comes up with the next prime on demand. So if you need the primes one at a time, in order, perhaps to call a function on each one, an iterator might be good. If you need to access the primes on demand, this won't do, however.
If you're looking for the first prime that meets some criteria, a generator is good, because you don't have to specify a range. No reason to generate the first thousand primes if you only need the first 100.
For example:
for prime in get_primes(2):
if meets_condition(prime):
return prime
will be better than:
primeList = primes(1000)
for prime in primeList:
if meets_condition(prime):
return prime
If n is small, but not if n is anywhere close to 1000.
Gotta go, sorry. I'll expand and proofread this later. Look up generators and prime sieves!
If you're working on a projecteuler.com problem, I'm going to go ahead and guess that the sieve will work better.

Categories

Resources