patternpythonModerate
Checking for the nth prime number between 1 and 1,000,000, must compute 1,000,000th in under 3 minutes
Viewed 0 times
nththenumber000thmustcompute000minutescheckingunder
Problem
My mission is as the title states.
Here is the original code, before optimizing slightly (but still not enough).
Revised code is in my answer, and it still needs work.
Also, I want to write this without having to import any libraries. Time is only there for me to test, of course, time.
Here's the original code, before optimizing:
Here is the original code, before optimizing slightly (but still not enough).
Revised code is in my answer, and it still needs work.
Also, I want to write this without having to import any libraries. Time is only there for me to test, of course, time.
Here's the original code, before optimizing:
print("Enter a number n, 1-1,000,000 to find the nth prime number.")
goal=int(input("Number: "))
if goal>1000000: #closes the program if the number doesn't fit the parameters
exit()
if goal==1: #takes care of the first prime, which is 2
print("2")
if goal==2: #and then the second, which is 3
print("3")
chk=5 #the next odd number after 3, which is already taken care of above
primes=2 #the number of primes recorded, after counting 2 and 3.
x=0 #the last recorded prime number
while primes9......
odds=3 #check to see if it's divisible by the smallest odd number
sqrtk=chk**.5 #all the way up to the square root of k
while oddssqrtk: #if k isn't divisible by any r
primes+=1 #we have a prime number
x=chk #record that number
chk+=2 #check the next odd number to see if it's prime
odds=3 #and reset r back to 3 to use it next time
if primes==goal: #once we've reached the desired amount of prime numbers
print("The",goal,"prime number is:",x) #print that prime numberSolution
Style (and related tools)
As described in Vogel612's answer, many things are wrong concerning the style. You can use pep8 (or its online version) to check it automatically and autopep8 to try to fix this automatically. You'll find various other convenient tools to check your code such as pylint, pyflakes or pychecker.
Separation of concerns and code organisation
You could create a function to look for the prime number and then call it when you want to print the result.
You'd get something like :
Also, the usage is to write your code "that actually does stuff" behind an
Testing
Having extracted a function to get the n-th prime number, you can more easily write test. You can play it simple, manually :
Or you can go further :
Now that we have test cases, rewriting the code is much easier.
A bit of logic
You can rewrite
Then you can rewrite this using range :
The check
Then you have :
Then you have
There is no need to compare
More functions
The test of primality can easily be written in a function on its own.
Luckily, I have this ready in my toolbox :
```
def is_prime(n):
"""Checks if a number is prime."""
if n 1000000:
return None
if goal == 1: # first prime is 2
ret
As described in Vogel612's answer, many things are wrong concerning the style. You can use pep8 (or its online version) to check it automatically and autopep8 to try to fix this automatically. You'll find various other convenient tools to check your code such as pylint, pyflakes or pychecker.
Separation of concerns and code organisation
You could create a function to look for the prime number and then call it when you want to print the result.
You'd get something like :
def get_nth_prime(goal):
if goal > 1000000:
return None
if goal == 1: # first prime is 2
return 2
if goal == 2: # second prime is 3
return 3
chk = 5 # the next odd number after 3, which is already taken care of above
primes = 2 # the number of primes recorded, after counting 2 and 3.
while primes 9......
odds = 3 # check to see if it's divisible by the smallest odd number
sqrtk = chk ** .5 # all the way up to the square root of chk
while odds sqrtk:
primes += 1 # we have a prime number
chk += 2 # check the next odd number to see if it's prime
odds = 3 # and reset odds back to 3 to use it next time
if primes == goal: # once we've reached the desired amount of prime numbers
return chk - 2
goal = int(input("Enter a number n, 1-1,000,000 to find the nth prime number."))
print("The", goal, "prime number is:", get_nth_prime(goal))Also, the usage is to write your code "that actually does stuff" behind an
if main guard so that you can import your code if you want to re-use your function without having any polluting. In your case, it becomes :def main():
"""Main function"""
goal = int(input("Enter a number n, 1-1,000,000 to find the nth prime number."))
print("The", goal, "prime number is:", get_nth_prime(goal))
if __name__ == "__main__":
main()Testing
Having extracted a function to get the n-th prime number, you can more easily write test. You can play it simple, manually :
assert get_nth_prime(1) == 2
assert get_nth_prime(2) == 3Or you can go further :
assert [get_nth_prime(i) for i in range(1, 100)] == [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, 521, 523]Now that we have test cases, rewriting the code is much easier.
A bit of logic
You can rewrite
while odds < sqrtk or odds == sqrtk: : while odds <= sqrtk:Then you can rewrite this using range :
while odds < sqrtk or odds == sqrtk: and then the second test can be written using the infamous else on the for loop (the best way to understand it is to read it as nobreak). The code becomes :for odds in range(3, int(chk ** .5) + 1, 2):
if chk % odds == 0: # ...chk is divisible by this odd number....
chk += 2 # then raise the value of chk to the next odd number
break # and start the check from the beginning with next k
else: # no break => no divisors => prime
primes += 1 # we have a prime number
chk += 2 # check the next odd number to see if it's primeThe check
if chk<9 looks like a premature optimisation to me. We can get rid of it.Then you have :
while primes no divisors => prime
primes += 1 # we have a prime number
chk += 2 # check the next odd number to see if it's primeThen you have
chk += 2 that appear in two different places : let's move it to a single place :while primes no divisors => prime
primes += 1
chk += 2
if primes == goal: # once we've reached the desired amount of prime numbers
return chk - 2There is no need to compare
primes and goal at every single iteration as it won't be updated that often : you can move this to the place where primes is increased :chk = 5 # the next odd number after 3, which is already taken care of above
primes = 2 # the number of primes recorded, after counting 2 and 3.
while True:
for odds in range(3, int(chk ** .5) + 1, 2):
if chk % odds == 0: # ...chk is divisible by this odd number....
break
else: # no break => no divisors => prime
primes += 1
if primes == goal:
return chk
chk += 2More functions
The test of primality can easily be written in a function on its own.
Luckily, I have this ready in my toolbox :
```
def is_prime(n):
"""Checks if a number is prime."""
if n 1000000:
return None
if goal == 1: # first prime is 2
ret
Code Snippets
def get_nth_prime(goal):
if goal > 1000000:
return None
if goal == 1: # first prime is 2
return 2
if goal == 2: # second prime is 3
return 3
chk = 5 # the next odd number after 3, which is already taken care of above
primes = 2 # the number of primes recorded, after counting 2 and 3.
while primes < goal:
if chk < 9: # if the number is odd and below 9....
primes += 1 # it's prime
chk += 2 # and check the next odd number
else: # if it's =>9......
odds = 3 # check to see if it's divisible by the smallest odd number
sqrtk = chk ** .5 # all the way up to the square root of chk
while odds < sqrtk or odds == sqrtk: # if at any time...
if chk % odds == 0: # ...chk is divisible by this odd number....
chk += 2 # then raise the value of chk to the next odd number
break # and start the check from the beginning with next k
else: # if not...
# check to see if it's divisible by the next odd number.
odds += 2
# if chk isn't divisible by any odds up to the square root of chk
if odds > sqrtk:
primes += 1 # we have a prime number
chk += 2 # check the next odd number to see if it's prime
odds = 3 # and reset odds back to 3 to use it next time
if primes == goal: # once we've reached the desired amount of prime numbers
return chk - 2
goal = int(input("Enter a number n, 1-1,000,000 to find the nth prime number."))
print("The", goal, "prime number is:", get_nth_prime(goal))def main():
"""Main function"""
goal = int(input("Enter a number n, 1-1,000,000 to find the nth prime number."))
print("The", goal, "prime number is:", get_nth_prime(goal))
if __name__ == "__main__":
main()assert get_nth_prime(1) == 2
assert get_nth_prime(2) == 3assert [get_nth_prime(i) for i in range(1, 100)] == [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, 521, 523]for odds in range(3, int(chk ** .5) + 1, 2):
if chk % odds == 0: # ...chk is divisible by this odd number....
chk += 2 # then raise the value of chk to the next odd number
break # and start the check from the beginning with next k
else: # no break => no divisors => prime
primes += 1 # we have a prime number
chk += 2 # check the next odd number to see if it's primeContext
StackExchange Code Review Q#66473, answer score: 10
Revisions (0)
No revisions yet.