This is the assignment my professor gave me. I have no idea where to start or what to do!
The point is to use loops to figure this out and I can do the loops, but this is blowing my mind.
Even numbers and primes.
A prime number is one that has 1 and itself as its only divisors. 2, 3, 5, 7 and 11 are the first several. Notice
that 'being prime' is purely a multiplicative condition -- it has nothing to do with addition. So it might be
surprising that if we start listing even numbers, they seem to be the sum (addition!) of two primes.
4 = 2 + 2, 6 = 3 + 3, 8 = 5 + 3, 10 = 3 + 7, 12 = 7 + 5, 14 = 7 + 7, 16 = 13 + 3, ...
Is this always the case? Can every even number be written as the sum of two primes?
Write a is_prime(n) function.
It should accept a positive integer n>1 as input, and output True or False, depending on whether n is or is not
a prime number. Do this with a loop that checks whether for any integer d, 1 < d < sqrt(n), d divides n.
I'd suggest a while loop -- think carefully about the conditional for the loop, and when you want to change
this conditional inside the loop. (Use a boolean for your condition).
Write a prime_sum(n) function.
It should accept an even number n>1 as input, and via a loop search for primes p & q with p + q = n.
Hint: start with p = 3. If (p) and (n-p) are prime you are done. If not, set p+=2 and try again.
Make sure you do not search forever!
Main.
Ask the user for an even number n. Continually ask them until they do give you a positive even number.
Search for the summands p & q, and either print them out (if they exist) or say they don't.
Ask the user if they wish to try with another even, and let them continue until they quit.
I didn't know I could edit this! :) So this is what I have so far. I have not tested it yet to debug it b/c I want to get it all down and when the errors pop up I will address them, but if you see any immediate problems let me know.
def is_prime(n):
d=2
while n>1 and d<n**0.5:
if n%2==0:
c=False
d+=1
return c
def prime_sum(n):
p=3
while n>1:
q=n-p
if q<=0:
p+=2
q=n-p
is_prime(q)
else:
is_prime(q)
is_prime(p)
while True:
print("The prime summands of", n, "are", p, "and", q)
while False:
print("There are no prime summands of", n)
def main():
n=eval(input("Gimme an even number please: "))
while True:
n=eval(input("That is not a positive even number. Try again: "))
#not sure how to combine yet, but I am still finishing.
#will edit again when I have it all down.
Don't worry about the big picture of the assignment being difficult. Just go step by step as the prof has broken it down.
Prime Number
A prime number (or a prime) is a
natural number that has exactly two
distinct natural number divisors: 1
and itself.
A)
def is_prime(n): # Write a is_prime(n) function.
if n <= 1: # It should accept a positive integer n>1
return False
if n == 2: # 2 has 2 divisors 1 and itself satisfying definition
return True
i = 2 # Start from 2 and check each number to the sqrt(n)
while i < n**0.5: # sqrt(n) can be written as n**0.5
if n % i == 0: # If n is divisible by i, which is not 1 or itself,
return False # return False (not prime)
i+=1 # Increment i by 1 and check looping condition
return True # If loop breaks, return True (prime)
Primes can be discovered in a variety of ways. This is one of the most basic with the only optimisation being that the divisor to check is stopped at the root of n instead of checking every number to n.
The most basic probably being:
def is_prime(n):
if n < 2:
return False
for i in range(2,n):
if n % i == 0:
return False
return True
B)
def prime_sum(n):
if n % 2 or n < 1: # if n is odd or less than 1 return invalid
return "invalid input"
p = 3
while n-p > 0:
if is_prime(p) and is_prime(n-p):
return (p, n-p) # if both conditions are met, return prime tuple
p+=2 # only check odd numbers
return "no answer found"
Related
This is my code. I am trying to find the prime numbers before or equal to the integer inputted. However, it seems that the loop stops when it sees an integer in the range that fits the requirements. Unfortunately, this is not I wanted it to do. I would like to make it run through all the tests in the range before making the judgement. Is this possible? If so, how do I do this? Thank you.
def getNumber(main):
n = int(input())
return n
def isPrime(n):
list=[2]
if n > 1:
for i in range(2, n+1):
for a in range (2, n):
if i*a != i and i%a != 0 and i%2 != 0:
list.append(i)
break
return "\n".join(map(str, list))`
def main():
n = getNumber(main)
print(isPrime(n))
main()
You've got your logic a bit wrong. Here's what your code is doing:
Examine numbers in increasing order from 2 to the inputted n.
For each number i, check if any number a between 2 and n divides i
If a divides i, add i to the list, and then move to the next i
This isn't going to get you a prime number. In fact, I'm having trouble figuring out what it will give you, but a prime number probably isn't it. Look at this function instead, which will return all the prime numbers less than or equal to the given number - you can compare it to your code to figure out where you went wrong:
def getPrimesLessThanOrEqualTo(n):
if n <= 1: # Anything 1 or less has no primes less than it.
return "" # So, return nothing.
list = [2] # 2 is the lowest prime number <= n
for i in range(3, n+1): # We start at 3 because there's no need to re-check 2
for a in list: # Instead of iterating through everything less than
# i, we can just see if i is divisible by any of
# the primes we've already found
if i % a == 0: # If one of the primes we've found divides i evenly...
break # then go ahead and try the next i
list.append(i) # Now, if we got through that last bit without
# hitting the break statement, we add i to our list
return "\n".join(list) # Finally, return our list of primes <= i
If you wanted to be more efficient, you could even use range(3, n+1, 2) to count by twos - thus avoiding looking at even numbers at all.
You can use a if/else block if your break is never executed by any item in the iterable the else statement will triggered. https://docs.python.org/3/tutorial/controlflow.html 4.4 demonstrates this accomplishing this almost exact task.
n = int(input('Enter number: '))
if n <= 1:
print('No primes')
else:
primes = []
for i in range(2, n +1):
for k in range(2, i):
if not i % k:
break
else:
primes.append(i)
print(*primes)
# Enter number: 50
# 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47
This program makes a list of all prime numbers less than or equal to a given input.
Then it prints the list.
I can't understand why it includes the number 2. When I first designed the program, I initialized the list with primes = [2] because I thought, since 2 % 2 == 0,
if n % x == 0:
is_prime = False
will set is_prime to False. However, that doesn't seem to be the case.
I'm sure there is something going on with the logic of my range() in the for loops that I just don't understand.
I guess my question is: Why is 2 included in the list of primes every time?
import math
limit = int(input("Enter a positive integer greater than 1: "))
while limit < 2:
limit = int(input("Error. Please enter a positive integer greater than 1: "))
primes = []
#Check all numbers n <= limit for primeness
for n in range (2, limit + 1):
square_root = int(math.sqrt(n))
is_prime = True
for x in range(2, (square_root + 1)):
if n % x == 0:
is_prime = False
if is_prime:
primes.append(n)
#print all the primes
print("The primes less than or equal to", limit, "are:")
for num in primes:
print(num)
Because you don't enter the second for-loop when you test for n=2 and therefore you don't set is_prime = False.
# Simplified test case:
x = 2
for idx in range(2, int(math.sqrt(x))+1):
print(idx)
This doesn't print anything because range is in this case: range(2, 2) and therefore has zero-length.
Note that your approach is not really efficient because:
you test each number by all possible divisors even if you already found out it's not a prime.
you don't exclude multiples of primes in your tests: if 2 is a prime, every multiple of 2 can't be prime, etc.
There are really great functions for finding prime numbers mentioned in Fastest way to list all primes below N - so I won't go into that. But if you're interested in improvements you might want to take a look.
Is there any suggestion on solving next higher prime and palindrome number from a given int.
Here is the snippet I am trying but its a kind of slow, please suggest if you ve any good algorithm that i can test.
#!/usr/bin/python
def next_higher(n):
while True:
s = str(n)
if not any([n % i == 0 \
for i in range(2, int(n**0.5))]) and s == s[::-1]:
return n
n = n + 1
print next_higher(2004)
print next_higher(20)
Output:
10201
101
Updated code testing for palindrome before prime. much faster than my previous code.
I am implementing the suggestion from user2357112.
#!/usr/bin/python
def next_higher(n):
while True:
s = str(n)
if s == s[::-1]:
if not any([n % i == 0 \
for i in range(2, int(n**0.5))]):
return n
n = n + 1
print next_higher(2004111)
print next_higher(2004)
print next_higher(2004)
print next_higher(20)
There are quite a few optimizations you could do:
Like user2357.. suggested in the comments, test palindromeness first, and then check if the number is prime, since prime check is more expensive.
You don't need to check even number divisibility once you check is the number is divisible by 2. So you can change it to [2] + range(3, int(n**0.5) + 1, 2) to check only odd numbers after 2. (Also you need to do sqrt + 1 like I mentioned in the comments)
You should use () instead of []. [] generates the entire list of factors first and only then checks for any. If you use (), it creates a generator, so it stops as soon as a True value is found without calculating the entire list.
You should also use xrange instead of range for the same reason (xrange gives a generator, range gives a list)
You can use the Sieve of Eratosthenes algorithm to significantly reduce the time taken for prime number check.
You can also see if the palindrome check can be made faster. You can actually skip a whole lot of numbers instead of doing just + 1 each time.
Here is a version with most of these optimizations except the last two:
def next_higher(n):
if n % 2 == 0:
n = n - 1
while True:
n = n + 2
s = str(n)
if s == s[::-1]:
if not any((n % i == 0 for i in xrange(3, int(n**0.5) + 1, 2))):
return n
This should be pretty fast for your needs I believe. But you can do the last 2 optimizations to make it much more faster if you want.
Other than what has already been suggested,
What I suggest is that you first get the first palindrome number that is just higher than the given integer.
You can do this by trying to match the centre digits outwards.
Also, you should only check for numbers with odd number of digits, since if a number has even number of digits and it is a palindrome, then it will always be divisible by 11 and cannot be prime.
Once you get the first palindrome number that has odd number of digits and that is just higher than the current number, test it for primality and find the next palindrome number higher than this one.
You can do this by incrementing the centre digit.
Keep doing this till it rolls over to zero. In that case start incrementing the two neighbouring digits.
Continue, till you reach a prime number.
I tried optimizing the palindrome check i.e to find odd palindrome's.
Since the first digit should be odd number, i focused on that part.
Here's the code below with the assumptions its greater than 1 digit.
def next_odd_palindrome(n):
"""to check the next odd palindrome number"""
if n%2==0:
n=n-1
while True:
n=n+2
s = str(n)
if int(s[0])%2==0:
n = int(str(int(s[0])+1)+ s[1:])
s = str(n)
if s==s[::-1]:
return n
let me know if anything wrong.
Just for the fun of it, I implemented all optimizations by Hari Shankar and Abhishek Bansal.
It first finds the higher odd length palindrome, then increment the palindrome in a way that keeps its palindromity. Then checks each number using prime numbers calculated by Sieve method in the beginning.
This can process up to n=10^14 (can be higher if you increase the CACHE size) under 1 second in my computer =D
primes = []
CACHE = int(10**7) # Cache size for Sieve
# Custom class for immediate printing of output
import sys
class Unbuf:
def __init__(self,stream):
self.stream = stream
def write(self,data):
self.stream.write(data)
self.stream.flush()
sys.stdout = Unbuf(sys.stdout)
def sieve():
global primes
is_prime = [False,False]+([True]*(CACHE-1))
for i in xrange(2,int(CACHE**0.5)):
if is_prime[i]:
is_prime[i*i::i] = [False]*((CACHE-i*i+i)/i)
primes = [num for num, bool_prime in enumerate(is_prime) if bool_prime]
def is_prime(n):
"""Checks whether n is prime"""
global primes
if n<2:
return False
if n==2:
return True
for prime in primes:
if prime>n**0.5+1:
return True
if n%prime==0:
return False
# For the case that the number is bigger than the square of our largest prime
for num in xrange(primes[-1]+2,n**0.5+1,2):
if n%num==0:
return False
return True
def next_higher_odd_length_palindrome(n):
n = str(n)
if len(n)%2==0: # Even length, take the smallest odd length (10(00)*1)
n = '1'+('0'*(len(n)-1))+'1'
else:
middle_idx = len(n)/2
left = int(n[:middle_idx+1])
left_cmp = n[middle_idx::-1]
right_cmp = n[middle_idx:]
# If mirroring left part to right part
# makes the number smaller or equal, then
if right_cmp>=left_cmp:
# Increase the left half number
left = left+1
# Mirror left part to the right part
n = str(left)+str(left)[-2::-1]
return n
def next_higher(n):
if n<=1:
return 2
# Ensure the number is a palindrome of odd length
n = next_higher_odd_length_palindrome(n)
while True:
if is_prime(int(n)):
return int(n)
n = next_higher_odd_length_palindrome(n)
if int(n[0])%2==0:
new_lead = str(int(n[0])+1)
n = new_lead+n[1:-1]+new_lead
import time
print 'Sieving...',
start_time = time.time()
sieve()
print 'Done in %.3fs' % (time.time() - start_time)
print next_higher(2004111)
print next_higher(2004)
print next_higher(20)
while True:
n = int(raw_input('Enter n: '))
start_time = time.time()
result = next_higher(n)
print 'Next higher prime palindrome: %d (calculated in %.3fs)' % (result, time.time() - start_time)
Which in my computer gives this output:
Sieving... Done in 1.444s
3007003
10301
101
Enter n: 1999999999
Next higher prime palindrome: 10000500001 (calculated in 0.004s)
Enter n: 1999999999999
Next higher prime palindrome: 3000002000003 (calculated in 0.051s)
Enter n: 1000000000000
Next higher prime palindrome: 1000008000001 (calculated in 0.030s)
Enter n:
I'm trying to find the largest prime factor for a number. The code runs correctly on IDLE when used with smaller numbers, but doesn't seem to print anything to the screen at all when I assign a larger number like 600851475143 to n. Why?
def isPrime(n):
isPrime = True
for i in range(2,n-1):
if n % i == 0:
isPrime = False
return isPrime
largest = 0
n = 600851475143
for i in range(2,n-1):
if isPrime(i) and n % i == 0:
largest = i
n = n / i
continue
print("The largest prime factor is", largest)
I'm running Python 3.3, by the way.
==============================================================================
Thanks everyone!
I fixed my original code as follows:
def isPrime(n):
for i in range(2,n-1):
if n % i == 0:
return False
return True
largest = 0
n = 600851475143
for i in range(2,n-1):
if isPrime(i) and n % i == 0:
largest = i
if i == n:
break
n = n / i
print("The largest prime factor is", largest)
Like nakedfanatic said, their code runs faster, and I edited it slightly:
largest = 0
n = 600851475143
i = 2
while True:
if n % i == 0:
largest = i
if n == i:
# finished
break
n = n / i
else:
i += 1
print("The largest prime factor is", largest)
There are several areas of optimization:
all factorization only needs to got up to sqrt(n) (inclusive)
convert isPrime() to a table lookup
Initialize a lookup table using n, then you compute all primes < sqrt(n) only once and loop through them.
As comments pointed out, this takes up large memory space. We can use bit flag to cut the memory requirement to 1/8, and we can cut it by a further half if we skip all the even numbers (then have to test if n is even separately). But that may still be daunting for LARGE n.
(if using current code) return early in isPrime() (by #justhalf)
loop backwards (from sqrt(n) to 2) when looking up the largest factor
return early if the quotient is 1 after dividing by a factor (by #justhalf)
This post (suggested by #prashant) contains more complicated algorithm (making my suggestion very naive ><):
Fastest way to list all primes below N
... (edits are welcome)
It's because you keep trying even if n is already 1.
This code will help you to see the problem:
def isPrime(n):
for i in xrange(2,n-1):
if n % i == 0:
return False
return True
largest = 0
n = 600851475143
for i in xrange(2,n-1):
print 'Checking whether %d divides %d' % (i,n)
if isPrime(i) and n % i == 0:
largest = i
n = n / i
continue
print("The largest prime factor is", largest)
which will produce:
...
Checking whether 6857 divides 6857
Checking whether 6858 divides 1
Checking whether 6859 divides 1
Checking whether 6860 divides 1
Checking whether 6861 divides 1
Checking whether 6862 divides 1
Checking whether 6863 divides 1
Checking whether 6864 divides 1
Checking whether 6865 divides 1
Checking whether 6866 divides 1
Checking whether 6867 divides 1
Checking whether 6868 divides 1
Checking whether 6869 divides 1
Checking whether 6870 divides 1
Checking whether 6871 divides 1
Checking whether 6872 divides 1
Checking whether 6873 divides 1
...
You should break the loop when n becomes 1, so that it won't do unnecessary checking
n = n / i
if n==1:
break
continue
And anyway, your code might be improved by a lot, haha, see others' suggestions.
Most likely, your code isn't terminating with large n, simply because it takes so long to run through the loop.
Your code is running in O(n²) time, which means it will quickly become unreasonably slow as the size of n increases. That is why your algorithm works for small values, but hangs for large values.
This code does the same thing in O(n) time without doing any prime checking at all, and returns a result instantly:
prime_factors = []
n = 600851475143
i = 2
while True:
if n % i == 0:
prime_factors.append(i)
if n == i:
# finished
break
n = n / i
else:
i += 1
print("The largest prime factor is", prime_factors[-1])
More difficult problems may require a different algorithm.
Check this question out: Fastest way to list all primes below N
Your code looks okay, but could take a long time for a large n. Leveraging math can enable you to do this problem orders of magnitude faster.
On that link, I recommend rwh_primes1 for a pure python solution, and primesfrom3to as one that uses numpy. Both of those implementations are fairly short, relatively clear, and do basically the same thing. Those code snippets are written in Python 2, so a translation might look like this:
def rwh_primes1(n):
sieve = [True] * (n//2)
for i in range(3, int(n**0.5)+1,2):
if sieve[i//2]:
sieve[i*i//2::i] = [False] * ((n-i*i-1)//(2*i)+1)
return [2] + [2*i+1 for i in range(1,n//2) if sieve[i]]
isPrime = True
for i in range(2,n-1):
if n % i == 0:
isPrime = False
return isPrime
This loop always exits the first iteration due to the unconditional return. Try:
for i in range(2,n-1):
if n % i == 0:
return False
return True
Also the upper bound n-1 can be reduced to sqrt(n)+1.
Another aspect of your code which may be slowing it down is the second half of your code
largest = 0
n = 600851475143
for i in range(2,n-1):
if isPrime(i) and n % i == 0:
largest = i
n = n / i
continue
Specifically the statement
if isPrime(i) and n % i == 0:
Per the documentation, the second condition is only evaluated if the first one is True. In your case it would make more sense to reverse the conditions so that computationally les expensive division is performed always and the more expensive isPrime() is only called for the actual factors
largest = 0
n = 600851475143
for i in range(2,n-1):
if n % i == 0 and isPrime(i):
largest = i
n = n / i
if n == 1:
break
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]