How could I make my prime generator function faster - python

to gain hands-on experience, I'm trying to solve the problems in spoj . The problem in the link asks to find all prime numbers between given 2 numbers. So how I implement this with python 2.7
# printing all prime numbers between given two inputs
import math
def findPrimes(num1,num2):
for num in range(num1,num2+1):
isPrime=True
for i in range(2,int(math.sqrt(num))+1):
if num%i==0:
isPrime=False
break
if isPrime:
print num
def main():
inputs=[]
numOfTestCases=int(raw_input())
while(numOfTestCases>0):
line=raw_input()
numbers=line.split()
inputs.append(numbers)
numOfTestCases-=1
for testCase in inputs:
findPrimes(int(testCase[0]),int(testCase[1]))
print ""
main()
However, when I send the code, I get time-exceed limit. How could I make my code fast enough?

You should use the Sieve of Eratosthenes and it is quite simple. First you initialize all numbers to be prime. Then for each prime you remove its multiples from the prime list. And it's time complexity is near liner O(nloglogn). Something like this:
N = 1000
is_prime = [1]*N
for i in xrange(2,N):
if is_prime[i]:
for j in xrange(2*i,N,i):
is_prime[j] = 0
This implementation should do just fine. But there are some extra optimizations that you can find them in the link above.
Note that 0 and 1 are not prime.

No, the numbers aren't huge in spoj/PRIME1. The sieve of Eratosthenes works extremely well there, but even trial division gets you through there, if you test by primes, and test odds only (or better, only 6-coprimes or 30-coprimes).
You need only find primes below the square root of your top limit, in advance. sqrt(10^9) is about 32,000, so there are only about 3,400 primes to maintain. That's nothing.
6-coprimes: numbers coprime with 6, i.e. with 2 and 3, so there's no need to test divide them by 2 nor 3, when testing for primes. You need to find a way to generate them directly, so there won't be any multiples of 2 and 3 among the numbers you need to test, by construction.

Related

what is the highest prime number between 1 and 10001

So I'm trying to find the 10,001 prime number. Yes, its the euler #7 problem. The code i wrote appears to give me all the prime numbers from 3 to 10,001 but my answer is still incorrect. I know there are other questions about this that have been answered but stealing someone else code does not help me learn. So I'm looking for insight into where i went wrong with this. First I seperated out all the odd numbers and added them to a list. I noticed that there were squares of some of the prime numbers in the list so I check the list against the squares of every number from 2 to 10,0001. That should have left me with nothing but prime numbers but I am still getting the wrong answer. Any ideas would be great thank you
prime = [i for i in range(2, 10002) if i % 2 != 0]
for i in range(2, 10002):
if i * i in prime:
prime.remove(i * i)
print(prime[-1])
Have you tried the case of 7*11=77? You're only looking in perfect squares when you should search multiples of all the known primes. In keeping with the theme of Project Euler, I'm not gonna give you the answer, but I_ can_ point you to the Sieve of Eratosthenes.
well actually... Since it's such an early problem, I'll dangle a spoiler.
Make a list of primes, initialize it to [2,3,5]. Starting from n=8 and increasing by six each time, check n-1 and n+1 for primality by testing modulos for each known primes from 2 to the square root of your number.

PYTHON: Finding an nth prime number

I've looked through a variety of older posts on this subject, and they have all left me confused in some way or another. So I'll start at the beginning.
The problem is #7 on Project Euler and I am a fairly new programmer trying to work my way through the problems. #7 is as follows.
By listing the first six prime numbers: 2, 3, 5, 7, 11, and 13, we can see that the 6th prime is 13.
What is the 10,001st prime number?
My issue is as follows. I have a clear understanding of what prime numbers are and how they work. The sudo-code I would write for this problem is this:
For n in range(3,n) #where n is some very large value.
if n%i ==0 for i in range(2,n-1)
return False
if n%i == 0 for i == n
return True
But I think my lack of knowledge when it comes to Python is impeding me in finding what I want.
In most of the other solutions I have seen, they limit n to something like 125000 and I honestly have no clue where they came up with that number from.
The other issue is I don't know how to search properly through a range and create a list of values that satisfied that relation in a manner that I can then check the Max value in the list.
The thing that would make the most sense to me would be to basically append each new prime to a list and then just take the max value, but I'm sure there is a better and faster way to do this. If you are going to answer, please include a healthy dose of explanation without jumping into python technobabble, remember, I'm a beginner in programming.
I know that the typical way people deal with questions like this is to prod the asker into finding the right answer, I don't want that. I would like someone to show me a solution and then walk through it step by step explaining what each part of the code does so that I can learn not only how to solve the problem, but also gain a better intuition for how python works.
Thanks.
This task basically asks you to gather 10001 prime numbers. So start by building a list of primes and when you reach the 10001th number display it.
Here is a sample code:
def is_prime(n):
for i in range(3, n):
if n % i == 0:
return False
return True
primes = [] # list of primes
x = 10001 # go to the nth-number
n = 2 # start at number 2
while len(primes) != x+1: # is n-th number on the list? +1 is because list is zero-based
if is_prime(n):
primes.append(n) # add prime to the list
n+=1 # increment n to check the next number
# print the last item in the list - the n-th number
print(primes[-1])

Issues in implementing Sieve of Eratosthenes algorithm

This is the 10th problem in project euler in which we are supposed to find the sum of all the prime numbers below 2 million. I am using Sieve of Eratosthenes algorithm to find the prime numbers. Now I am facing and performance issue with the Sieve of Eratosthenes algorithm.
The performance goes down by a substantial amount if the print(i,"",sum_of_prime) is kept inside the loop. Is there anyway to see it working and keep the performance? If this is done with the conventional method it take some 13 minutes to get the result.
#Euler 10
#Problem:
#The sum of the primes below 10 is 2 + 3 + 5 + 7 = 17.
#Find the sum of all the primes below two million.
#Author: Kshithij Iyer
#Date of creation: 15/1/2017
import time
#Recording start time of the program
start=time.time()
def sum_of_prime_numbers(limit):
"A function to get the sum prime numbers till the limit"
#Variable to store the sum of prime numbers
sum_of_prime=0
#Sieve of Eratosthenes algorithm
sieve=[True]*limit
for i in range(2,limit):
if sieve[i]:
sum_of_prime=sum_of_prime+i
for j in range(i*i,limit,i):
sieve[j]=False
print(i,"",sum_of_prime)
print("The sum of all the prime numbers below",limit,"is",sum_of_prime)
return
#sum_of_prime_numbers(10)
sum_of_prime_numbers(2000001)
print("Execution time of program is",time.time()-start)
#Note:
#I did give the conventioanl method a try but it didn't work well and was taking
#some 13 minutes to get the results.
#Algorithm for reference
#Input: an integer n > 1
#Let A be an array of Boolean values, indexed by integers 2 to n,
#initially all set to true.
#for i = 2, 3, 4, ..., not exceeding √n:
#if A[i] is true:
#for j = i2, i2+i, i2+2i, i2+3i, ..., not exceeding n :
#A[j] := false
#Output: all i such that A[i] is true.
So there are various improvements that could be made here:
Firstly, due to the nature of Eratosthenes' sieve, you can replace for i in range(2,limit): with for i in range(2,int(limit**0.5)+1): and the array will be calculated normally, but much faster; however, as a result, you would then have to sum the numbers later.
Also, you are not going to be able to read every individual prime and nor would you want to; instead, you only need the program to tell you milestones, such as every time the program reaches a certain number to check everything against.
Your program does not appear to take into account the fact that arrays start at 0, which should certainly cause some problems; however, this should be fairly fixable.
Finally, it occurs to me that your program appears to count 1 as prime; this should be another easy fix though.

Trying to understand a solution to project Euler # 3

The prime factors of 13195 are 5, 7, 13 and 29.
What is the largest prime factor of the number 600851475143 ? # http://projecteuler.net/problem=3
I have a deal going with myself that if I can't solve a project Euler problem I will understand the best solution I can find. I did write an algorithm which worked for smaller numbers but was too inefficient to work for bigger ones. So I googled Zach Denton's answer and started studying it.
Here is his code:
#!/usr/bin/env python
import math
def factorize(n):
res = []
# iterate over all even numbers first.
while n % 2 == 0:
res.append(2)
n //= 2
# try odd numbers up to sqrt(n)
limit = math.sqrt(n+1)
i = 3
while i <= limit:
if n % i == 0:
res.append(i)
n //= i
limit = math.sqrt(n+i)
else:
i += 2
if n != 1:
res.append(n)
return res
print max(factorize(600851475143))
Here are the bits I can't figure out for myself:
In the second while loop, why does he use a sqrt(n + 1) instead of just sqrt(n)?
Why wouldn't you also use sqrt(n + 1) when iterating over the even numbers in the first while loop?
How does the algorithm manage to find only prime factors? In the algorithm I first wrote I had a separate test for checking whether a factor was prime, but he doesn't bother.
I suspect the +1 has to do with the imprecision of float (I am not sure whether it's actually required, or is simply a defensive move on the author's part).
The first while loop factors all twos out of n. I don't see how sqrt(n + 1) would fit in there.
If you work from small factor to large factors, you automatically eliminate all composite candidates. Think about it: once you've factored out 5, you've automatically factored out 10, 15, 20 etc. No need to check whether they're prime or not: by that point n will not be divisible by them.
I suspect that checking for primality is what's killing your original algorithm's performance.

Reduce time complexity of brute forcing - largest prime factor

I am writing a code to find the largest prime factor of a very large number.
Problem 3 of Project Euler :
What is the largest prime factor of the number 600851475143 ?
I coded it in C...but the data type long long int is not sufficient enough to hold the value .
Now, I have rewritten the code in Python. How can I reduce the time taken for execution (as it is taking a considerable amount of time)?
def isprime(b):
x=2
while x<=b/2:
if(b%x)==0:
return 0
x+=1
return 1
def lpf(a):
x=2
i=2
while i<=a/2:
if a%i==0:
if isprime(i)==1:
if i>x:
x=i
print(x)
i+=1
print("final answer"+x)
z=600851475143
lpf(z)
There are many possible algorithmic speed ups. Some basic ones might be:
First, if you are only interested in the largest prime factor, you should check for them from the largest possible ones, not smallest. So instead of looping from 2 to a/2 try to check from a downto 2.
You could load the database of primes instead of using isprime function (there are dozens of such files in the net)
Also, only odd numbers can be primes (except for 2) so you can "jump" 2 values in each iteration
Your isprime checker could also be speededup, you do not have to look for divisiors up to b/2, it is enough to check to sqrt(b), which reduces complexity from O(n) to O(sqrt(n)) (assuming that modulo operation is constant time).
You could use the 128 int provided by GCC: http://gcc.gnu.org/onlinedocs/gcc/_005f_005fint128.html . This way, you can continue to use C and avoid having to optimize Python's speed. In addition, you can always add your own custom storage type to hold numbers bigger than long long in C.
I think you're checking too many numbers (incrementing by 1 and starting at 2 in each case). If you want to check is_prime by trial division, you need to divide by fewer numbers: only odd numbers to start (better yet, only primes). You can range over odd numbers in python the following way:
for x in range(3, some_limit, 2):
if some_number % x == 0:
etc.
In addition, once you have a list of primes, you should be able to run through that list backwards (because the question asks for highest prime factor) and test if any of those primes evenly divides into the number.
Lastly, people usually go up to the square-root of a number when checking trial division because anything past the square-root is not going to provide new information. Consider 100:
1 x 100
2 x 50
5 x 20
10 x 10
20 x 5
etc.
You can find all the important divisor information by just checking up to the square root of the number. This tip is useful both for testing primes and for testing where to start looking for a potential divisor for that huge number.
First off, your two while loops only need to go up to the sqrt(n) since you will have hit anything past that earlier (you then need to check a/i for primeness as well). In addition, if you find the lowest number that divides it, and the result of the division is prime, then you have found the largest.
First, correct your isprime function:
def isprime(b):
x=2
sqrtb = sqrt(b)
while x<=sqrtb:
if(b%x)==0:
return 0
x+=1
return 1
Then, your lpf:
def lpf(a):
x=2
i=2
sqrta = sqrt(a)
while i<=sqrt(a):
if a%i==0:
b = a//i # integer
if isprime(b):
return b
if isprime(i):
x=i
print(x)
i+=1
return x

Categories