I have a weird problem with my program.
When n<=100 it works just fine.
However when it comes to bigger numbers(such as n=121) it keeps showing me this message:
File "my_code.py2", line 24, in
print k[int(n)]
IndexError: list index out of range
Code:
k=[]
z=[]
a=0
k.append(1)
k.append(2)
k.append(3)
n=raw_input()
while n!="END" and int(n)>0 and int(n)%100000==int(n):
for x in xrange(3,7919,2):
for i in xrange(3,x,2):
if x%i!=0:
a=1
else:
a=0
break
if a==1:
k.append(x)
if len(k)==int(n):
break
print k[int(n)]
n=raw_input()
Can you help me???
I think you have an off-by-one error. Python uses zero based-indexing, so to get the 121st element you would want to access your list at k[120].
By the way, 1 is not a prime number.
edit: Rather than fix up other issues with the code that you've mention in the comments, might I suggest a better algorithm? Rather than checking for divisors, the sieve of eratosthenes is the usual way of listing all primes below a bound. It's easy to implement and should be faster than your current method with nested loops.
This is because you break the loop when len(k) == int(n) and then access k[int(n)]. Since python uses 0 based indexing, when the list length is equal to n, the last index you can access is n-1.
As you add 1 to the list, and 1 is not a prime, every other prime in the list will have their actual index.
I.e 2 is at index 1, and 2 is the first prime.
3 is at index 2, and 3 is the second prime.
So, the solution is to change len(k) == int(n) to len(k) == int(n) + 1.
NOTE: There is an another issue with your program. When ever the statements inside the outer loop get excuted. It keeps adding elements to k unnecessarily. So, what i suggest is first calculate all the primes upto a certain limit. And then just query that list. Don't repeatedly calculate all the primes from the beginning.
k=[]
z=[]
a=0
k.append(1)
k.append(2)
k.append(3)
for x in xrange(3,7919,2):
for i in xrange(3,x,2):
if x%i!=0:
a=1
else:
a=0
break
if a==1:
k.append(x)
n = raw_input()
while n!="END" and int(n)>0 and int(n) < len(k):
print k[int(n)]
n = raw_input()
Related
I want to find the largest prime number within range(old_number + 1 , 2*old_number)
This is my code so far:
def get_nearest_prime(self, old_number):
for num in range(old_number + 1, 2 * old_number) :
for i in range(2,num):
if num % i == 0:
break
return num
when I call the get_nearest_prime(13)
the correct output should be 23, while my result was 25.
Anyone can help me to solve this problem? Help will be appreciated!
There are lots of changes you could make, but which ones you should make depend on what you want to accomplish. The biggest problem with your code as it stands is that you're successfully identifying primes with the break and then not doing anything with that information. Here's a minimal change that does roughly the same thing.
def get_nearest_prime(old_number):
largest_prime = 0
for num in range(old_number + 1, 2 * old_number) :
for i in range(2,num):
if num % i == 0:
break
else:
largest_prime = num
return largest_prime
We're using the largest_prime local variable to keep track of all the primes you find (since you iterate through them in increasing order). The else clause is triggered any time you exit the inner for loop "normally" (i.e., without hitting the break clause). In other words, any time you've found a prime.
Here's a slightly faster solution.
import numpy as np
def seive(n):
mask = np.ones(n+1)
mask[:2] = 0
for i in range(2, int(n**.5)+1):
if not mask[i]:
continue
mask[i*i::i] = 0
return np.argwhere(mask)
def get_nearest_prime(old_number):
try:
n = np.max(seive(2*old_number-1))
if n < old_number+1:
return None
return n
except ValueError:
return None
It does roughly the same thing, but it uses an algorithm called the "Sieve of Eratosthenes" to speed up the finding of primes (as opposed to the "trial division" you're using). It isn't the fastest Sieve in the world, but it's reasonably understandable without too many tweaks.
In either case, if you're calling this a bunch of times you'll probably want to keep track of all the primes you've found since computing them is expensive. Caching is easy and flexible in Python, and there are dozens of ways to make that happen if you do need the speed boost.
Note that I'm not positive the range you've specified always contains a prime. It very well might, and if it does you can get away with a lot shorter code. Something like the following.
def get_nearest_prime(old_number):
return np.max(seive(2*old_number-1))
I don't completely agree with the name you've chosen since the largest prime in that interval is usually not the closest prime to old_number, but I think this is what you're looking for anyway.
You can use a sublist to check if the number is prime, if all(i % n for n in range(2, i)) means that number is prime due to the fact that all values returned from modulo were True, not 0. From there you can append those values to a list called primes and then take the max of that list.
List comprehension:
num = 13
l = [*range(num, (2*num)+1)]
print(max([i for i in l if all([i % n for n in range(2,i)])]))
Expanded:
num = 13
l = [*range(num, (2*num)+1)]
primes = []
for i in l:
if all([i % n for n in range(2, i)]):
primes.append(i)
print(max(primes))
23
Search for the nearest prime number from above using the seive function
def get_nearest_prime(old_number):
return old_number+min(seive(2*old_number-1)-old_number, key=lambda a:a<0)
I'm trying to create a python program to check if a given number "n" is prime or not. I've first created a program that lists the divisors of n:
import math
def factors(n):
i = 2
factlist = []
while i <= n:
if n% i == 0:
factlist.append(i)
i = i + 1
return factlist
factors(100)
Next, I'm trying to use the "for i in" function to say that if p1 (the list of factors of n) only includes n itself, then print TRUE, and if else, print FALSE. This seems really easy, but I cannot get it to work. This is what I've done so far:
def isPrime(n):
p1 = factors(n)
for i in p1:
if factors(n) == int(i):
return True
return False
Any help is appreciated! This is a hw assignment, so it's required to use the list of factors in our prime test. Thanks in advance!
p1 will only have n if if has length 1. It may be worthwhile to add if len(p1)==1 as the conditional instead.
What I did (I actually managed to get it in 1 line) was use [number for number in range (2, num // 2) if num % number == 0]. This gets all the numbers that are factors of num. Then you can check if the length of that list is > 0. (Wouldn't be prime).
I usually do something like this:
primes = [2,3]
def is_prime(num):
if num>primes[-1]:
for i in range(primes[-1]+2, num+1,2):
if all(i%p for p in primes):
primes.append(i)
return num in primes
This method generates a global list of prime numbers as it goes. It uses that list to find other prime numbers. The advantage of this method is fewer calculations the program has to make, especially when there are many repeated calls to the is_prime function for possible prime numbers that are less than the largest number you have previously sent to it.
You can adapt some of the concepts in this function for your HW.
I wrote this Python code to print all the prime numbers until 1000:
primes = []
for prime in xrange(1, 1000):
for b in xrange(2, prime):
if (prime % b == 0):
break
else:
primes.append(prime)
print primes
However, if a number is a prime, it is appended a lot of times before moving to the next number. I tried using continue instead of break but that does not work.
I also added some more code onto that (which works) to simply output the array into a text file. It is so large that I cannot even paste it into here.
How can I append each prime number to the list only once instead of many times?
There's a feature in Python you can use quite effectively here. Just change your indentation like this:
primes = []
for prime in xrange(1, 1000):
for b in xrange(2, prime):
if (prime % b == 0):
break
else:
primes.append(prime)
print primes
That is, de-indent the else clause. This way it is not the else of the if but of the for loop. A for loop can have an else branch which gets executed after the loop has performed all scheduled iterations. If there is a break called, it gets not executed.
You can use that here without having to change a lot of your original code.
Of course, in your original version, each loop iteration in which a tested number did not turn out to be a non-prime, that tested number got appended (which was not what you wanted).
Also note that 1 is not a prime number (at least since Gauss in 1801, some say even since Euclid (600BC) first wrote about prime numbers, although there were heretics since into the 19th century), so your outer loop should start at 2 instead.
But note what Daniel wrote in his answer; you do not have to step through all the way to prime because after reaching the square root of prime, you can bail out. I always compared b * b to prime, but maybe computing sqrt(prime) once even is faster.
And of course, you can be faster by ignoring all even numbers completely. Except 2 none are prime ;-)
You need to only add the number if it reaches the end of the loop without it finding a divisor.
from math import sqrt
prime = True
for b in xrange(2, sqrt(prime)):
if prime % b == 0:
prime = False
break
if prime:
primes.append(prime)
Note I've added an optimization: you only need to test up the square root of a number, because anything after that can't possibly divide.
I need to find the nth prime number, in the fastest way possible in Ruby or Python:
require "prime"
puts Prime.first(n).join("")
This takes a lot of time for numbers >= 100000.
How do I optimize this code?
Give this a try:-
# Steps
# List first 'n' prime
# Choose the very last one
require "prime"
def nprime(n)
(Prime.first n).last
end
puts nprime(10001)
It gave me the answer preety quick:
$ ruby nprime.rb
104743
You may try this dynamic program in python, this looks up in a dictionary of primes(built dynamically by the program itself), which is initially empty and it gets faster as you find larger primes.
dict = {}
def prime(x):
dict[1] = 2
s = x
if x in dict:
return dict[s]
else:
while s > 0:
if s in dict:
pno = int(dict[s]) + 1
break
s-=1
while s < x:
m = 1
while m <= s:
if pno % dict[m] == 0:
pno+=1
m=1
else:
m+=1
dict[s+1]= pno
s+=1
return dict[x]
initially build the dictionary for lower primes for speeding up higher ones. Example to find the 10000th prime, do the following in python shell ahen running the module:
prime(1000)
prime(5000)
prime(10000)
Prime ruby doc.
require "prime"
Prime::EratosthenesSieve.instance.get_nth_prime(1000000)
I just started to learn python and system programming. For a homework assignment, I need to find and print the nth prime number. I wrote the code below - I can find a list of prime numbers that are less than or equal to n, however, I don't know how I can print the nth prime from the list I created. I keep getting the index error: list index out of range.
I believe I'm missing something. Can someone take a look at my code and give me some guidance on how to fix it? Your help is greatly appreciated. Thank you.
import sys
import math
def s_prime(n):
is_prime=list(range(n+1))
for i in range(2, int(n**0.5)+1):
if is_prime[i]:
for j in range(i**2,n+1,i):
is_prime[j]=False
print 'Prime Value in Decimal: ', [x for x in is_prime[2:] if x]
x_list = [x for x in is_prime[2:] if x]
print x_list[n-1]
def main(argv):
input = int(sys.argv[1])
if input == 1:
print 2
elif input == 2:
print 3
else:
n = int(round(input*(math.log(input,2))))
s_prime(n)
if __name__ == "__main__":
main(sys.argv[1:])
As you changed the value of n here, n = int(round(input*(math.log(input,2)))). It is now something bigger than the original n. For example when input = 5, n is 12 and clearly the x_list contains only 5 items so you're going to get IndexError as index 11 is out of bound.
You can either using negative indexing here:
return x_list[-1] to get the last element.
or pass the original input to the prime function:
def s_prime(n, inp):
print n
#you code here....
print x_list[inp-1]
def main(argv):
#your code
n = int(round(input*(math.log(input,2))))
s_prime(n, input) #pass input here
The problem here is that you generate primes up to n and store them in a list. Clearly, this list has fewer than n items, so when you try to find the nth prime, you get the "index out of range error".
To fix this, you can generate primes as you go until you find the nth prime, or you can pick a larger upper bound for generating your list of primes. You can use this to help you pick this upper bound.