Enumeration to find Nth prime with Python - python

I have decided it is about time that i should start learning to code. I have some knowledge of HTML and CSS but i want to be able to develop for iOS. I am aware i have a long way to go, but i aim to get there step by step.
I'm working through the MIT Python course on iTunes U and I am stuck on the homework. I understand the concept of enumeration and testing every possible outcome to find the primes, however what i have tried so far has failed me. My closest attempt is the following.
# counting confirmed primes. For loop should do remainder tests on
# all testNumbers, unless caught by the if statements that rule out
# multiples of 2,3,5,7 to speed things up. divisor increments by one
# on those numbers that do not get pulled by qualifying if statements
testNumber = 2
confirmedPrime = 0
while (confirmedPrime < 1001):
for divisor in range(1, testNumber+1):
if (testNumber/2)*2== testNumber:
testNumber += 1
elif (testNumber/3)*3 == testNumber:
testNumber += 1
elif (testNumber/5)*5 == testNumber:
testNumber += 1
elif (testNumber/7)*7 == testNumber:
testNumber += 1
elif(testNumber%divisor == 0):
testNumber += 1
confirmedPrime +=1
print testNumber
This however doesn't return the "7919" i am expecting but. It returns "7507" So somewhere there are some composites slipping through the net.
I have hunted through this site and not managed to solve it so I thought I would ask.

A few bits are off here, so let's go step by step.
You start by setting initial values, which is perfectly reasonable.
testNumber=2
confirmedPrime = 0
Then you go into a while loop, continuing until the value of the variable confirmedPrime is has reached (i.e. is equal to or bigger than) 1001. I suppose your task is to find the 1000th prime, but doing it like this you're actually finding the 1001st, because the while loop continues until confirmedPrime has the value of 1001. Change it to
while(confirmedPrime < 1000):
You immediately go into another loop, and here comes the first problem, even though it isn't what's giving you the wrong answer.
for divisor in range(1, testNumber+1)
if (testNumber/2)*2 == testNumber:
...
Doing the tests for multipliers of 2, 3, 5 and 7 inside the for loop doesn't make any sense, as you only have to to this once for each value of testNumber. So that part of the testing should be moved out of the for loop.
if (testNumber/2)*2 = testNumber: # Why not use modulo here too for consistency?
testNumber += 1
elif ...
...
else:
for divisor in range(...):
The next part is testing for other, larger divisors. You are testing divisors in the range 1 to testNumber+1. I'm not sure why you're doing this, but it's not a good idea, as your modulo test will always return zero when you come to the second last iteration, testing testNumber%testNumber. So you should change it to testNumber-1, in fact you can stop when you have reached the square root of testNumber, but I'll leave it to you to figure out why.
Now comes the biggest problem:
After the for loop is finished, you increment confirmedPrimes by 1 without actually checking if you found a prime or not. So, incrementing confirmedPrimes should only happen if none of the first tests were true and none of the "divisor tests" turned out to be true.
Rewritten using underscores instead of mixedCase (which is bad python mojo), consistent spacing etc:
import math
test_number = 7 # Already know up to 7
confirmed_primes = 4 # Already know about 2, 3, 5 and 7
while confirmed_primes < 1000:
test_number += 1
if test_number % 2 and test_number % 3 and test_number % 5 and test_number % 7:
is_prime = True
for divisor in range(11, int(math.sqrt(test_number))+1):
if test_number % divisor == 0:
is_prime = False
if is_prime:
confirmed_primes += 1
print test_number

I don't understand exactly how your algorithm is supposed to find a prime number.
A number is said to be prime if it's only divisible by 1 or himself.
Another definition is that a number is said to be prime if it's not divisible by any prime number smaller than it.
This can be the base of your algorithm, speeding up the process by a lot.
def nth_prime(n):
prime_list = []
current = 2
count = 0
while(count < n):
is_prime = True
for prime in prime_list:
if current % prime == 0:
is_prime = False
break
if is_prime:
prime_list.append(current)
count += 1
current += 1
return current - 1
print nth_prime(1000) # => 7919

Related

While loop doesn't read condition

I'm trying to make a program that will stop when it gets 5 prime numbers from a range.
I've completed most of the program except the part where it is supposed to stop after it gets 5 numbers.
I've added a condition for it to stop, once the counter reaches 5 but it does not stop and continues to list all the numbers in the range.
Here is code I have:
condition = 0
while condition < 5:
for numbers in range(2,20):
for divisor in range(2,numbers):
if (numbers % divisor) == 0:
break
else:
print(numbers)
condition +=1
The condition+=1 never goes through and it lists all the prime numbers from 1 to 20 even though I just want the first 5.
I've tried spacing options with the "condition +=1" but it still does not work
Any help would be appreciated
While is out of for loop, so cannot work obviously. A simple solution is to check required condition later:
for numbers in range(2,20):
for divisor in range(2,numbers):
if (numbers % divisor) == 0:
break
else:
print(numbers)
condition +=1
if condition >=5:
break
I think the real problem you are having is that you have written bad code. A much better approach to this problem is to isolate as many pieces as possible.
for example:
def is_prime(x):
"return true if x is prime, otherwise false"
# implement me!
return True
def get_first_n_primes_less_than_y(n, y):
number = 2
condition = 0
while condition != n and number < y:
if is_prime(number):
print(number)
condition += 1
number += 1
get_first_n_primes(5, 20)
The above code, with some tweaking can perform the same task. However, code like this is much simpler to debug and reason about because we have isolated chunks of code (is_prime, has nothing to do with the while loop)
num_results = 5
counter = 0
range_start = 2
range_end = 20
# iterate range
for number in range (range_start, range_end):
# iterate divisors
for divisor in range (2, number):
# check division
if (number % divisor) == 0:
break
else:
print ("%s is a prime number" % number)
counter += 1
break
# check if number of results has been reached
if counter == num_results:
break
# check if number of results has been reached
if counter == num_results:
break
The problem is that you need to run the entire content of the while block before you test the condition again.
Here is a way around
condition = 0
numbers=2
while condition < 5 and numbers < 20:
for divisor in range(2,numbers):
if (numbers % divisor) == 0:
break
else:
print(numbers)
condition +=1
numbers+=1

Calculating the thousandth prime

The problem asks to calculate the 1000th prime number. I am trying to solve this problem but I am stuck.
There are some guidelines on how to solve the problem.
To help you get started, here is a rough outline of the stages you should probably follow in
writing your code:
Initialize some state variables
Generate all (odd) integers > 1 as candidates to be prime
For each candidate integer, test whether it is prime
One easy way to do this is to test whether any other integer > 1 evenly
divides the candidate with 0 remainder. To do this, you can use modular
arithmetic, for example, the expression a%b returns the remainder after
dividing the integer a by the integer b.
You might think about which integers you need to check as divisors –
certainly you don’t need to go beyond the candidate you are checking, buthow much sooner can you stop checking?
If the candidate is prime, print out some information so you know where you are
in the computation, and update the state variables
Stop when you reach some appropriate end condition. In formulating this
condition, don’t forget that your program did not generate the first prime (2).
Use these ideas to guide the creation of your code.
My attempt so far is this
def calculate_thousandth_prime():
j = 0
for i in range(3,int(10e6)):
if i%2 != 0:
counter = 0
for k in range(1, i):
if i%k != 0:
counter += 1
if counter == 0:
print("This candidate is prime")
j += 1
if j == 1001:
print("The number "+str(i)+" is the thousandth prime")
break
return 0
calculate_thousandth_prime()
My code gets stuck on i%k != 0. I must be doing something wrong... any help?
You have two problems:
First, you're searching for k in range(1, i):. Because every number, including primes, is divisible by 1, you won't find any primes. Try searching range(2, i) instead.
Second, you're checking if i%k != 0:. You should be checking that i%k == 0 instead. If i is divisible by any number k, then the number is not prime.
Actually, I found a third issue: You have an off-by-one error. By initializing j=0, your code considers the first prime it finds to be the "zeroth" prime. The code will output the thousand-and-first prime, instead of the thousandth prime.
Changes I made:
Change your range to add a 2 step to skip even numbers more naturally.
Check your inner loop, you need to divide by the values range(2, i//2). Dividing by anything greater than i//2 will be less than 2.
Change your prime check to see if any number in the above range divides. If so, we know the number is false. At that point we can move onto the next number.
We want to return when the prime counter is 1000, you were returning the 1001th prime.
def calculate_thousandth_prime():
prime_counter = 0
for i in range(3,int(10e6),2):
prime = True
for k in range(2, i//2):
if i % k == 0:
prime = False
break
if prime:
print(str(i) + " is prime")
prime_counter += 1
if prime_counter == 1000:
print("The number "+str(i)+" is the thousandth prime")
break
return i
calculate_thousandth_prime()
The sieve of Eratosthenes is generally the fastest way for the early primes. You can adapt it to reach the nth prime.
For example:
def nthPrime(N):
sieve = [1]*(N**2)
p = 2
for _ in range(N):
while not sieve[p]: p += 1
sieve[p::p] = [0]*len(sieve[p::p])
return p
nthPrime(100) # 541
The prime list divisor check method is probably easier to write and understand but it is much slower (although for only 1000 primes, this wouldn't make much of a difference):
def nthPrime(N):
primes = [2]
p = 1
while len(primes)<N:
p += 2
primes += [p]*all(p%d for d in primes)
return p

Better algorithm on prime numbers

I'm working on a program which will found the nth. prime number. For example, By listing the first six prime numbers: 2, 3, 5, 7, 11 and 13, we can see that the 6th prime is 13. I'm trying to making an algorithm, like, if I want to see 50th prime, I will add 1 to ends of the range() function. I'm using this algorithm to find primes at the moment;
cnt = 1
print (2)
for x in range(3,40,2):
div = False
for y in range(2,round(x**0.5)+1):
if x%y == 0:
div = True
if div == False:
print (x)
cnt += 1
print ("\nThere is {} prime numbers.".format(cnt))
You see that, I put 40. But I want to put n there, so for example, untill reaching the 50th prime, add +1 to n. But it's not going to like that, if I tried something like;
cnt = 1
n = 40 #example
while cnt<50:
for x in range(3,n,2):
#codes
if div == False:
n += 1
I thought when the program finds a prime, it will add +1 to n and while loop will process untill find the 50th prime. But it didn't, primes are wrong if I use this one also, nothing relevant what I want to do.
How to make this algorithm, obviously changing the last element of range() function does not working.
Is there better/elegant algorithm/way? If I want to find 200.000th prime, I need faster codes.
Edit: I was working with lists first but, I got MemoryError all the time when working with big numbers. So I pass that and using a variable that counting how much primes are there cnt.
Here is a much faster version
primes = []
primecount = 0
candidate = 2
while primecount<50:
is_prime = True
for prime in primes:
if candidate%prime == 0:
is_prime = False
break
elif candidate < prime**2:
break
if is_prime:
primes.append(candidate)
primecount += 1
candidate += 1
print primes[-1]
note small edit adding the candidate<prime**2 test that OP included but I neglected initially.
Your code is going to be very slow for several reasons. If 2 divides a number you know it's not prime, but you're still checking whether 3 or 4 or 5... divides it. So you can break out as soon as you know it's not prime. Another major issue is that if 2 does not divide a number, there's no reason to check if 4 divides it as well. So you can restrict your attention to just checking if the primes coming before it divide it.
In terms of run time:
First off, for backwards compatibility with python 2, I added an int() around your rounding of root x.
From what I understand of your question, you are looking for something like this:
cnt = 1
maximum=50 #Specify the number you don't want the primes to exceed
print (2)
n=20 #highest number
while cnt<maximum: #
for x in range(3,n,2): #using "n" as you hoped
div = False
for y in range(2,int(round(x**0.5)+1)):
if x%y == 0:
div = True
if div == False:
if x<maximum: #we only want to print those up to the maximum
print str(x)
else: #if it is greater than the maximum, break the for loop
break
cnt += 1
break #break the while loop too.
print ("\nThere are {} prime numbers.".format(cnt))
This gave me the correct primes. As for better/more elegant solutions. If by better you want speed, use a library that has an optimized, or look at this for an example of a fast program. Elegance is subjective, so I will leave that to the rest of the internet.

Part of this prime number program is just not making sense to me

Could someone explain
for k in range(2, 1+int(sqrt(i+1))):
to me? I am having a hard time comprehending how
1+int(sqrt(i+1)
truly works.
I understand 1 is being added to i, and it is being square rooted, and it must be an integer. But I don't comprehend how that achieves the goal of the whole program
from math import sqrt
count = 1
i = 1
while count < 1000:
i += 2
for k in range(2, 1+int(sqrt(i+1))):
if i%k == 0:
break
else:
# print(i) ,
count += 1
# if count%20==0: print ""
print i
whose goal is to find the 1000th prime.
If a number is to be tested for primality, it is sufficient to test all factors up to sqrt(number), because any factor above sqrt(number) has a corresponding factor below sqrt(number).
e.g. if you want to test if 36 is prime, it is sufficient to test up to 6 - for example, 12 is a factor of 36, but its other factor is 3, which you already tested by then.

Calculating prime numbers

I am now doing the MIT opencourse thing, and already the second assignment, I feel it has left me out in the cold. http://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-00-introduction-to-computer-science-and-programming-fall-2008/assignments/pset1a.pdf
The specifics of it, are to write something that can calculate the 1000th prime number. We only know about the print, ==, =, 1=,if, else, elif, while, %, -,+,*,/, commands I think. We also don't yet know about importing libraries.
My Idea of how it would work is to take an odd number and try to divide it by, 3,4,5,6,7,8,9 and if %n !=0, then add a number to NumberofPrimes variable starting with 11 as the base of the tests, and assigning it a base value of 4 at the base of NumberofPrimes, though I don't know if that is even right, because I wouldn't know how to display the 1000th prime number.
Am I close?
The latest incarnation of it is as follows:
##calculate the 1000th prime number
potprime = 3
numberofprime = 1
cycle = if potprime%3 = 0:
break
if potpimre%4 = 0:
break
if potprime%5 = 0:
break
if potprime%6 = 0:
break
if potprime%7 = 0:
break
if potprime%8 = 0:
break
if potprime%9 = 0:
break
numberofprime + 1
potprime + 1
if potprime%2 == 0:
potprime = potprime + 1
if potprime != 0:
cycle
Where exactly am I going wrong? Walk me through it step by step. I really want to learn it, though I feel like I am just being left out in the cold here.
At this point, it would be more beneficial for me to see how a proper one could be done rather than doing this. I have been working for 3 hours and have gotten nowhere with it. If anybody has a solution, I would be more than happy to look at it and try to learn from that.
Looks like I am late
It is quite straight forward that if a number is not divisible by any prime number, then that number is itself a prime number. You can use this fact to minimize number of divisions.
For that you need to maintain a list of prime numbers. And for each number only try to divide with prime numbers already in the list. To optimize further it you can discard all prime numbers more than square root of the number to be tested. You will need to import sqrt() function for that.
For example, if you test on 1001, try to test with 3, 5, 7, 11, 13, 17, 19, 23, 29 and 31. That should be enough. Also never try to find out if an even number is prime. So basically if you test an odd number n, then after that test next number: (n + 2)
Have tested the below code. The 1000th prime number is 7919. Not a big number!!
Code may be like:
from math import sqrt
primeList = [2]
num = 3
isPrime = 1
while len(primeList) < 1000:
sqrtNum = sqrt(num)
# test by dividing with only prime numbers
for primeNumber in primeList:
# skip testing with prime numbers greater than square root of number
if num % primeNumber == 0:
isPrime = 0
break
if primeNumber > sqrtNum:
break
if isPrime == 1:
primeList.append(num)
else:
isPrime = 1
#skip even numbers
num += 2
# print 1000th prime number
print primeList[999]
The following code is gross, but since 1000 is indeed a small index, it solves your problem in a fraction of a second (and it uses only the primitives you are supposed to know so far):
primesFound = 0
number = 1
while primesFound < 1000:
number = number + 1 # start from 2
# test for primality
divisor = 2
numberIsPrime = True
while divisor*divisor <= number: # while divisor <= sqrt(number)
if number % divisor == 0:
numberIsPrime = False
break
divisor = divisor + 1
# found one?
if numberIsPrime:
primesFound = primesFound + 1
print number
You can test the solution here.
Now you should find a more efficient solution, optimize and maybe go for the 1000000-th prime...
For one thing, I'm pretty sure that in Python, if you want to have an if statement that tests whether or not A = B, you need to use the == operator, rather then the =.
For another thing, your algorithm would consider the number 143 to be prime, even though 143 = 11 * 13
You need keep track of all the prime numbers that you have already computed - add them to an array. Use that array to determine whether or not a new number that you are testing is prime.
It seems to me that you are jumping into the deep-end after deciding the kiddy-pool is too deep. The prime number project will be assignment 2 or 3 in most beginning programming classes, just after basic syntax is covered. Rather than help you with the algorithm (there are many good ones out there) I'm going to suggest that you attempt to learn syntax with the python shell before you write long programs, since debugging a line is easier than debugging an entire program. Here is what you wrote in a way that will actually run:
count = 4
n = 10 #I'm starting you at 10 because your method
#says that 2, 3, 5, and 7 are not prime
d = [2, 3, 4, 5, 6, 7, 8, 9] #a list containing the ints you were dividing by
def cycle(n): #This is how you define a function
for i in d: #i will be each value in the list d
if not n%i: #this is equal to if n%i == 0
return 0 #not prime (well, according to this anyway)
return 1 #prime
while count < 1000:
count += cycle(n) #adds the return from cycle to count
n += 1
print n - 1
The answer is still incorrect because that is not how to test for a prime. But knowing a little syntax would at least get you that wrong answer, which is better than a lot of tracebacks.
(Also, I realize lists, for loops, and functions were not in the list of things you say you know.)
Your code for this answer can be condensed merely to this:
prime_count = 1
start_number = 2
number_to_check = 2
while prime_count <= 1000:
result = number_to_check % start_number
if result > 0:
start_number +=1
elif result == 0:
if start_number == number_to_check:
print (number_to_check)
number_to_check +=1
prime_count +=1
start_number =2
else:
number_to_check +=1
start_number = 2
To answer your subsequent question, 'How do I keep track of all the prime numbers?
One way of doing this is to make a list.
primeList = [] # initializes a list
Then, each time you test a number for whether it is prime or not, add that number to primeList
You can do this by using the 'append' function.
primeList.append( potprime ) # adds each prime number to that list
Then you will see the list filling up with numbers so after the first three primes it looks like this:
>>> primeList
[11, 13, 17]
Your math is failing you. A prime number is a number that has 2 divisors: 1 and itself. You are not testing the numbers for primality.
I am very late on this but maybe my answer will be of use to someone. I am doing the same open course at MIT and this is the solution I came up with. It returns the correct 1000th prime and the correct 100,000th prime and various others in between that I have tested. I think this is a correct solution (not the most efficient I am sure but a working solution I think).
#Initialise some variables
candidate = 1
prime_counter = 1
while prime_counter < 1000:
test = 2
candidate = candidate + 2
# While there is a remainder the number is potentially prime.
while candidate%test > 0:
test = test + 1
# No remainder and test = candidate means candidate is prime.
if candidate == test:
prime_counter = prime_counter + 1
print "The 1000th prime is: " + str(candidate)
While I was at it I went on and did the second part of the assignment. The question is posed as follows:
"There is a cute result from number theory that states that for sufficiently large n the product of the primes less than n is less than or equal to e^n and that as n grows, this becomes a tight bound (that is, the ratio of the product of the primes to e^n gets close to 1 as n grows).
Computing a product of a large number of prime numbers can result in a very large number,
which can potentially cause problems with our computation. (We will be talking about how
computers deal with numbers a bit later in the term.) So we can convert the product of a set of primes into a sum of the logarithms of the primes by applying logarithms to both parts of this conjecture. In this case, the conjecture above reduces to the claim that the sum of the
logarithms of all the primes less than n is less than n, and that as n grows, the ratio of this sum to n gets close to 1."
Here is my solution. I print the result for every 1,000th prime up to the 10,000th prime.
from math import *
#Initialise some variables
candidate = 1
prime_counter = 1
sum_logs = log(2)
while prime_counter < 10000:
test = 2
candidate = candidate + 2
# While there is a remainder the number is potentially prime.
while candidate%test > 0:
test = test + 1
# No remainder and test = candidate means candidate is prime.
if candidate == test:
prime_counter = prime_counter + 1
# If the number is prime add its log to the sum of logs.
sum_logs = sum_logs + log(candidate)
if prime_counter%1000 == 0:
# For every 1000th prime print the result.
print sum_logs," ",candidate," ",sum_logs/candidate
print "The 10000th prime is: " + str(candidate)
Cheers,
Adrian
I came up with this solution in my interview, but I didn't get the job :( It has about 1/100 less iterations than the solution above:
from math import *
MAX_IDX=1000
MAX_IDX-=1
num_iter=0
l_pirme_list=[3]
candidate=l_pirme_list[0]
prime_counter=1
while prime_counter < MAX_IDX:
candidate+=2
#Cut the binary number in half. This is quite faster than sqrt()
bin_candidate=format(candidate, "2b")
max_prime_search=int(bin_candidate[:len(bin_candidate)/2+1],2)+1
# max_prime_search=sqrt(candidate)+1
candidate_is_prime=1
for prime_item in l_pirme_list:
num_iter+=1
if candidate % prime_item==0:
candidate_is_prime=0
break
elif prime_item > max_prime_search:
candidate_is_prime=1
break
if candidate_is_prime:
prime_counter+=1
l_pirme_list.append(candidate)
l_pirme_list.insert(0,2)
print "number iterations=", num_iter
print l_pirme_list[MAX_IDX]

Categories