Memory Limit Exceed to find N-th prime - python

I was solving a problem (on a website) to print N-th prime number where N is an user input. The problem fixed those limits 1s, 512 MB. I wrote that code bellow.
n = int(input())
r = (n+1)**2
nth = n - 1
d = [x for x in range(2, r)]
non_prime = []
for i in range(2, r):
for x in d:
if i % x == 0 and x != 1 and x != i:
non_prime.append(i)
non_prime = list(set(non_prime))
prime_numbers = [x for x in d if x not in non_prime]
print(prime_numbers[nth])
Now the code works perfectly but after submitting it says Memory Limit Exceeded. How to solve that without changing my code excessively??
(I know there is much easier way to solve that problem. But I solve it on my own.)

The method you are using checks every number up to the square of a given number. I find it much easier to add prime numbers to a list and check its length. Using this method, it checks few numbers and can run fast.
def getPrime(num):
arr = []
x = 2
while len(arr) < num:
prime = True
for divisor in range(2, x):
if x % divisor == 0 and prime == True:
prime = False
if prime == True:
arr.append(x)
x += 1
return arr[num - 1]
I encourage you improve this code, as it is rudimentary.
Edit: I corrected a variable name.

Related

python 3 prime number wrong answer yield why this code give me wrong prime factor like 9,21,.......?

primef = []
def i_prime(n) :
count = 0
for i in range ( 0, n ):
for j in range ( 2, i ):
if (not i % j == 0):
yield i
count += 1
else:
break
for i in i_prime(45):
primef.append(i)
primefe = list(set(primef))
print(primefe)
There seems be some flaw in your logic. What you have essentially made is an odd number generator (think about why). Since that part is already answered, here are some tips:
I would not suggest this algorithm to generate prime numbers as it
is inefficient. You could alternatively cache all yielded prime
numbers in a list and only check against that list instead of the
for j in range(2, i):.
There is even more efficient way to generate prime numbers by
utilizing a fact from number theory which states that all prime
numbers greater than 3 are of the form 6k+1 or 6k+5 where k is an integer, which is non-negative for practical purposes (the explanation behind which is fairly simple).
Here is a piece of code I wrote while solving a Project Euler question:
def is_prime(x: int) -> bool:
if x <= 3:
return x > 1
elif x % 2 == 0 or x % 3 == 0:
return False
i = 5
while i*i <= x:
if x % i == 0 or x % (i + 2) == 0:
return False
i = i + 6
return True
This prime checker served as a useful generator for me to find the 10001st prime number in 0.6s (for a Project Euler question).
Ask me any questions, if you have any, related to this implementation.
This is corrected version of your code - you need to go through all the possible factors before deciding that a number is not prime - you are yielding the value as soon as there is one number that it does not divide by.
primef = []
def i_prime(n) :
for i in range ( 0, n ):
for j in range ( 2, i ):
if (i % j == 0):
break
else:
yield i
for i in i_prime(45):
primef.append(i)
print(primef)

Eulers problem №3, code stucks on big numbers

I'm currently learning Python, and practice with euler's problem's.
I'm stuck on 3rd problem, my code didn't working on the big numbers, but with other number's it's working.
n = 600851475143
x = 0
for i in range(2,n):
if(n%i == 0):
if(x < i): x = i
print(x)
The console just didn't get any results and stucks.
P.S https://projecteuler.net/problem=3
(sorry for my bad english)
It's running, but just the time it takes is huge.
You can check by the following code, it keeps going to print x's.
n = 600851475143
x = 0
for i in range(2, n):
if n % i == 0:
if x < i:
x = i
print(x)
To save time, you can try the following code instead of your code:
n = 600851475143
x = 0
for i in range(2, n):
if n % i == 0:
x = n // i
break
print(x)
which prints 8462696833 instantly. But as #seesharper stated on the comment, it is merely the largest factor and not a prime factor. So it is not the correct answer to the Project Euler Problem #3.
Check this code you will save a lot of time
Using sqrt for optimization
from math import sqrt
def Euler3(n):
x=int(sqrt(n))
for i in range(2,x+1):
while n % i == 0:
n //= i
if n == 1 or n == i:
return i
return n
n = int(input())
print(Euler3(n))
Also, check my Euler git repo
There are only 6 solutions in python2 and it's pretty old but they are very well optimized.
from tqdm.auto import tqdm
n = 600851475143
x = 0
for i in tqdm(range(2,n)):
if(n%i == 0):
x = i
print(x)
If using classic python, your program will last for at least 40 min, that's why you had no output. I suggest you either use numpy to go through, or add a step because I think even numbers won't work.
I used tqdm to estimate the time needed for the for loop to run, you can download it using pip install tqdm
What would be more efficient is to only divide your number by actual primes. You also only need to check divisors up to the square root of the number given that any valid (integer) result will be also be a divisor (which you will already have checked if your divisor goes beyond the square root).
# generator to obtain primes up to N
# (sieve of Eratosthenes)
def primes(N):
isPrime = [True]*(N+1)
p = 2
while p<=N:
if isPrime[p]:
yield p
isPrime[p::p] = (False for _ in isPrime[p::p])
p += 1 + p>2
# use the max function on primes up to the square root
# filtered to only include those that divide the number
n = 600851475143
result = max(p for p in primes(int(n**0.5)+1) if n%p == 0)
print(result) # 6857
Alternatively, you can use sequential divisions to find factors while reducing the number as you go along. This will cause each new factor you find to be a prime number because divisions by all smaller numbers will already have been done and removed from the remaining number. It will also greatly reduce the number of iterations when your number has many prime factors.
def primeFactors(N): # prime factors generator
d,d2 = 2,4 # start divisors at first prime (2)
while d2<=N: # no need to go beyond √N
if N%d:
d += 1 + (d&1) # progress by 2 from 3 onward
d2 = d*d # use square of d as limiter
else:
yield d # return prime factor
N //= d # and reduce number
if N>1: yield N # final number could be last factor
print(*primeFactors(600851475143)) # 71 839 1471 6857
print(max(primeFactors(600851475143))) # 6857

Python print non-prime numbers

I have a hackkerank coding challenge to print first n non prime numbers, i have the working code but the problem is that they have a locked code which prints numbers from 1 to n along with the output, in order to pass the test i need to print only the non prime numbers not 1...n numbers along with it. I cant comment the printing part of 1...n as it is blocked. please let me know the idea to print only 1st n non prime numbers:
here is my solution:
def manipulate_generator(generator, n):
if n>1:
ls=[1]
for elm in generator:
if elm>3 and len(ls)<n:
for k in range(2,elm):
if elm%k==0 and elm not in ls:
ls.append(elm)
print(elm)
if len(ls)==n:
return ls
That's the code I added but here is the code that's locked on which I have to write the code above to make it print the number one at a time
def positive_integers_generator():
n = 1
while True:
x = yield n
if x is not None:
n = x
else:
n += 1
k = int(input())
g = positive_integers_generator()
for _ in range(k):
n = next(g)
print(n)
manipulate_generator(g, n)
the point is the for _ in range(k): already prints out number which includes numbers I don't want printed out: This is the desired kind of output I want:for n=10 I want it to print out:
output:
1
4
6
8
9
10
12
14
15
16
I can't change this code but the one above is what I wrote and can be changed... Pleae help me out... Thanks in anticipation
Why not to throw away the numbers which we don't need? Look at this solution which I implemented...
def is_prime(n):
for i in range(2, n):
if n%i == 0:
return False
return True
def manipulate_generator(generator, n):
if is_prime(n+1):
next(generator)
manipulate_generator(generator, n+1)
Note: I understand that the logic can be improved to make it more efficient. But, its the idea of skipping unnecessary number printing which is important here !
You can print all the numbers from 1 up to the first prime number and then from that first number to the next one until you reach n.
I'm not sure of your hackerrank situation, but printing the first N non-prime numbers efficiently can be done this way.
def non_prime_numbers_till_n(n):
primes = set()
for num in range(2,number + 1):
if num > 1:
for i in range(2, math.sqrt(num)):
if (num % i) == 0:
break
else:
primes.add(num)
result = []
for i in range(1, n):
if i not in primes:
result.append(i)
return result
Depending on what your online editor expects you can either print them, or store them in a list and return the list.
Also bear in mind, you can only check upto the sqrt of the number to determine if its a prime or not.
I eventually came up with this answer which I believe should solve it but id there;s a better way to solve it please add your answers:
def manipulate_generator(generator, n):
for num in range(3,100000):
for q in range(2,num):
if num%q==0 and num>n:
generator.send(num-1)
return
this link python generator helped me to understand python generator
I just solved that right now. Like Swapnil Godse said you need to deal with all special cases to optimize computations. This link might be helpful: click here.
Here is the solution:
from math import sqrt
def is_prime(n):
if (n <= 1):
return False
if (n == 2):
return True
if (n % 2 == 0):
return False
i = 3
while i <= sqrt(n):
if n % i == 0:
return False
i = i + 2
return True
def manipulate_generator(g, n):
if is_prime(n+1):
next(g)
manipulate_generator(g, n+1)
prime = int(input('Please enter the range: '))
prime_number = []
for num in range(prime):
if num > 1:
for i in range(2,num):
if num % i == 0:
break
else:
prime_number.append(num)
print(f'Prime numbers in range {prime} is {prime_number}')
all_number = []
for i in range(2,prime+1):
all_number.append(i)
Non_prime_number = []
for element in all_number:
if element not in prime_number:
Non_prime_number.append(element)
print(f'Non Prime numbers in range {prime} is {Non_prime_number}')

Project Euler #7 Python

I'm having trouble with my code. The question is:
"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?"
This is what it looks like:
div = 10001
i = 2
count = 0
prime = 0
now = []
while count < div:
for x in range (2,i+1):
if len(now) ==2:
break
elif i%x == 0:
now.append(x)
if len(now)==1:
prime = i
count += 1
now = []
i+=1
print(prime)
I have tried div up to 1000 and it seems to work fine(for div 1000 I receive 7919). However, when I try div = 10001 I get nothing, not even errors. If someone would help me out I would really appreciate it.
Thank you.
# 7 10001st prime
import itertools
def is_prime(n):
for i in range(2, n//2 + 1):
if n % i == 0:
return False
else:
continue
return True
p = 0
for x in itertools.count(1):
if is_prime(x):
if p == 10001:
print(x)
break
p += 1
Try this code:
prime_list = lambda x:[i for i in xrange(2, x+1) if all([i%x for x in xrange(2, int(i**0.5+1))])][10000]
print prime_list(120000)
Lambda in Python defines an anonymous function and xrange is similar to range, defining a range of integer numbers. The code uses list comprehension and goes through the numbers twice up to the square root of the final number (thus i**0.5). Each number gets eliminated if it is a multiple of the number that's in the range count. You are left with a list of prime numbers in order. So, you just have to print out the number with the right index.
With just some simple modifications (and simplifications) to your code, you can compute the number you're looking for in 1/3 of a second. First, we only check up to the square root as #Hashman suggests. Next, we only test and divide by odd numbers, dealing with 2 as a special case up front. Finally, we toss the whole now array length logic and simply take advantage of Python's break logic:
limit = 10001
i = 3
count = 1
prime = 2
while count < limit:
for x in range(3, int(i ** 0.5) + 1, 2):
if i % x == 0:
break
else: # no break
prime = i
count += 1
i += 2
print(prime)
As before, this gives us 7919 for a limit of 1000 and it gives us 104743 for a limit of 10001. But this still is not as fast as a sieve.
m=0
n=None
s=1
while s<=10001:
for i in range(1,m):
if m%i==0:n=i
if n==1:print(m,'is prime',s);s+=1
m+=1

Euler Project #3 in Python

I'm trying to solve the Project Euler problem 3 in Python:
The prime factors of 13195 are 5, 7, 13 and 29.
What is the largest prime factor of the number 600851475143 ?
I know my program is inefficient and oversized, but I just wanted to know why doesn't it work?
Here's the code:
def check(z):
# checks if the given integer is prime
for i in range(2, z):
if z % i == 0:
return False
break
i = i+1
return True
def primegen(y):
# generates a list of prime integers in the given range
tab = []
while y >= 2:
if check(y) == True:
tab.append(y)
i = i-1
def mainfuntion(x):
# main function; prints the largest prime factor of the given integer
primegen(x)
for i in range(len(tab)):
if x % tab[i] == 0:
print tab[i]
break
mainfuntion(600851475143)
And here's the error:
for i in range(2, z):
OverflowError: range() result has too many items
The reason is that a list in Python is limited to 536,870,912 elements (see How Big can a Python Array Get?) and when you create the range in your example, the number of elements exceeds that number, causing the error.
The fun of Project Euler is figuring out the stuff on your own (which I know you're doing :) ), so I will give one very small hint that will bypass that error. Think about what a factor of a number is - you know that it is impossible for 600851475142 to be a factor of 600851475143. Therefore you wouldn't have to check all the way up to that number. Following that logic, is there a way you can significantly reduce the range that you check? If you do a bit of research into the properties of prime factors, you may find something interesting :)
This is the code that I used!!
n = 600851475143
i = 2
while i * i < n:
while n % i == 0:
n = n / i
i = i + 1
print n
-M1K3
#seamonkey8: Your code can be improved. You can increase it by 2 rather than one. It makes a speed difference for really high numbers:
n,i = 6008514751231312143,2
while i*i <= n:
if n%i == 0:
n //= i
else:
i+=[1,2][i>2]

Categories

Resources