The problem:
Given an array of integers nums containing n + 1 integers where each integer is in the range [1, n] inclusive.
There is only one repeated number in nums, return this repeated number.
You must solve the problem without modifying the array nums and uses only constant
extra space.
Here is one of the possible solution using binary search
class Solution(object):
def findDuplicate(self, nums):
beg, end = 1, len(nums)-1
while beg + 1 <= end:
mid, count = (beg + end)//2, 0
for num in nums:
if num <= mid: count += 1
if count <= mid:
beg = mid + 1
else:
end = mid
return end
Example 1:
Input: nums = [1,3,4,2,2]
Output: 2
Example 2:
Input: nums = [3,1,3,4,2]
Output: 3
Can someone please explain this solution for me? I understand the code but I don't understand the logic behind this. In particular, I do not understand how to construct the if statements (lines 7 - 13). Why and how do you know that when num <= mid then I need to do count += 1 and so on. Many thanks.
The solution keeps halving the range of numbers the answer can still be in.
For example, if the function starts with nums == [1, 3, 4, 2, 2], then the duplicate number must be between 1 and 4 inclusive by definition.
By counting how many of the numbers are smaller than or equal to the middle of that range (2), you can decide if the duplicate must be in the upper or lower half of that range. Since the actual number is greater (3 numbers are lesser than or equal to 2, and 3 > 2), the number must be in the lower half.
Repeating the process, knowing that the number must be between 1 and 2 inclusive, only 1 number is less than or equal to the middle of that range (1), which means the number must be in the upper half, and is 2.
Consider a slightly longer series: [1, 2, 5, 6, 3, 4, 3, 7]. Between 1 and 7 lies 3, 4 numbers are less than or equal to 3, so the number must be between 1 and 3. Between 1 and 3 lies 2, 2 numbers are less than or equal to 2, so the number must be over 2, which leaves 3.
The solution will iterate over all n elements of nums a limited number of times, since it keeps halving the search space. It's certainly more efficient than the naive:
def findDuplicate(self, nums):
for i, n in enumerate(nums):
for j, m in enumerate(nums):
if i != j and n == m:
return n
But as user #fas suggests in the comments, this is better:
def findDuplicate(nums):
p = 1
while p < len(nums):
p <<= 1
r = 0
for n in nums:
r ^= n
for n in range(len(nums), p):
r ^= n
return r
This is how given binary search works. Inside binary search you have implementation of isDuplicateLessOrEqualTo(x):
mid, count = (beg + end)//2, 0
for num in nums:
if num <= mid: count += 1
if count <= mid:
return False # In this case there are no duplicates less or equal than mid.
# Actually count == mid would be enough, count < mid is impossible.
else:
return True # In this case there is a duplicate less or equal than mid.
isDuplicateLessOrEqualTo(x) is a non-decreasing function (assume x has a duplicate, then for all i < x it's false and for all i >= x it's true), that's why you can run binary search over it.
Each iteration you run through the array, which gives you overall complexity O(n log n) (where n is size of array).
There's a faster solution. Note that xor(0..(2^n)-1) = 0 for n >= 2, because there are 2^(n-1) ones for each bit position and it's an even number, for example:
0_10 = 00_2
1_10 = 01_2
2_10 = 10_2
3_10 = 11_2
^
2 ones here, 2 is even
^
2 ones here, 2 is even
So by xor-ing all the numbers you'll receive exactly your duplicate number. Let's write it:
class Solution(object):
def nearestPowerOfTwo(number):
lowerBoundDegreeOfTwo = number.bit_length()
lowerBoundDegreeOfTwo = max(lowerBoundDegreeOfTwo, 2)
return 2 ** lowerBoundDegreeOfTwo
def findDuplicate(self, nums):
xorSum = 0
for i in nums:
xorSum = xorSum ^ i
for i in range(len(nums), nearestPowerOfTwo(len(nums) - 1)):
xorSum = xorSum ^ i
return xorSum
As you can see that gives us O(n) complexity.
If anyone is interested in a different approach (not binary search) to solve this problem:
Sum all elements of the array - we will call it sumArray - the time complexity is O(n).
Sum all numbers from 1 to n (inclusive) - we will call it sumGeneral - this is simply (n * (n+1) / 2) - the time complexity is O(1).
Return the result of sumArray - sumGeneral
In total, the time complexity is O(n) (you cannot do better since you have to look at all elements of the array, potentially the repeated one is at the end), and additional space complexity is O(1).
(If you could use O(n) additional space complexity you could use a hash table)
Two part question:
Trying to determine the largest prime factor of 600851475143, I found this program online that seems to work. The problem is, I'm having a hard time figuring out how it works exactly, though I understand the basics of what the program is doing. Also, I'd like if you could shed some light on any method you may know of finding prime factors, perhaps without testing every number, and how your method works.
Here's the code that I found online for prime factorization [NOTE: This code is incorrect. See Stefan's answer below for better code.]:
n = 600851475143
i = 2
while i * i < n:
while n % i == 0:
n = n / i
i = i + 1
print(n)
#takes about ~0.01secs
Why is that code so much faster than this code, which is just to test the speed and has no real purpose other than that?
i = 1
while i < 100:
i += 1
#takes about ~3secs
This question was the first link that popped up when I googled "python prime factorization".
As pointed out by #quangpn88, this algorithm is wrong (!) for perfect squares such as n = 4, 9, 16, ... However, #quangpn88's fix does not work either, since it will yield incorrect results if the largest prime factor occurs 3 or more times, e.g., n = 2*2*2 = 8 or n = 2*3*3*3 = 54.
I believe a correct, brute-force algorithm in Python is:
def largest_prime_factor(n):
i = 2
while i * i <= n:
if n % i:
i += 1
else:
n //= i
return n
Don't use this in performance code, but it's OK for quick tests with moderately large numbers:
In [1]: %timeit largest_prime_factor(600851475143)
1000 loops, best of 3: 388 µs per loop
If the complete prime factorization is sought, this is the brute-force algorithm:
def prime_factors(n):
i = 2
factors = []
while i * i <= n:
if n % i:
i += 1
else:
n //= i
factors.append(i)
if n > 1:
factors.append(n)
return factors
Ok. So you said you understand the basics, but you're not sure EXACTLY how it works. First of all, this is a great answer to the Project Euler question it stems from. I've done a lot of research into this problem and this is by far the simplest response.
For the purpose of explanation, I'll let n = 20. To run the real Project Euler problem, let n = 600851475143.
n = 20
i = 2
while i * i < n:
while n%i == 0:
n = n / i
i = i + 1
print (n)
This explanation uses two while loops. The biggest thing to remember about while loops is that they run until they are no longer true.
The outer loop states that while i * i isn't greater than n (because the largest prime factor will never be larger than the square root of n), add 1 to i after the inner loop runs.
The inner loop states that while i divides evenly into n, replace n with n divided by i. This loop runs continuously until it is no longer true. For n=20 and i=2, n is replaced by 10, then again by 5. Because 2 doesn't evenly divide into 5, the loop stops with n=5 and the outer loop finishes, producing i+1=3.
Finally, because 3 squared is greater than 5, the outer loop is no longer true and prints the result of n.
Thanks for posting this. I looked at the code forever before realizing how exactly it worked. Hopefully, this is what you're looking for in a response. If not, let me know and I can explain further.
It looks like people are doing the Project Euler thing where you code the solution yourself. For everyone else who wants to get work done, there's the primefac module which does very large numbers very quickly:
#!python
import primefac
import sys
n = int( sys.argv[1] )
factors = list( primefac.primefac(n) )
print '\n'.join(map(str, factors))
For prime number generation I always use the Sieve of Eratosthenes:
def primes(n):
if n<=2:
return []
sieve=[True]*(n+1)
for x in range(3,int(n**0.5)+1,2):
for y in range(3,(n//x)+1,2):
sieve[(x*y)]=False
return [2]+[i for i in range(3,n,2) if sieve[i]]
In [42]: %timeit primes(10**5)
10 loops, best of 3: 60.4 ms per loop
In [43]: %timeit primes(10**6)
1 loops, best of 3: 1.01 s per loop
You can use Miller-Rabin primality test to check whether a number is prime or not. You can find its Python implementations here.
Always use timeit module to time your code, the 2nd one takes just 15us:
def func():
n = 600851475143
i = 2
while i * i < n:
while n % i == 0:
n = n / i
i = i + 1
In [19]: %timeit func()
1000 loops, best of 3: 1.35 ms per loop
def func():
i=1
while i<100:i+=1
....:
In [21]: %timeit func()
10000 loops, best of 3: 15.3 us per loop
If you are looking for pre-written code that is well maintained, use the function sympy.ntheory.primefactors from SymPy.
It returns a sorted list of prime factors of n.
>>> from sympy.ntheory import primefactors
>>> primefactors(6008)
[2, 751]
Pass the list to max() to get the biggest prime factor: max(primefactors(6008))
In case you want the prime factors of n and also the multiplicities of each of them, use sympy.ntheory.factorint.
Given a positive integer n, factorint(n) returns a dict containing the
prime factors of n as keys and their respective multiplicities as
values.
>>> from sympy.ntheory import factorint
>>> factorint(6008) # 6008 = (2**3) * (751**1)
{2: 3, 751: 1}
The code is tested against Python 3.6.9 and SymPy 1.1.1.
"""
The prime factors of 13195 are 5, 7, 13 and 29.
What is the largest prime factor of the number 600851475143 ?
"""
from sympy import primefactors
print(primefactors(600851475143)[-1])
def find_prime_facs(n):
list_of_factors=[]
i=2
while n>1:
if n%i==0:
list_of_factors.append(i)
n=n/i
i=i-1
i+=1
return list_of_factors
Isn't largest prime factor of 27 is 3 ??
The above code might be fastest,but it fails on 27 right ?
27 = 3*3*3
The above code returns 1
As far as I know.....1 is neither prime nor composite
I think, this is the better code
def prime_factors(n):
factors=[]
d=2
while(d*d<=n):
while(n>1):
while n%d==0:
factors.append(d)
n=n/d
d+=1
return factors[-1]
Another way of doing this:
import sys
n = int(sys.argv[1])
result = []
for i in xrange(2,n):
while n % i == 0:
#print i,"|",n
n = n/i
result.append(i)
if n == 1:
break
if n > 1: result.append(n)
print result
sample output :
python test.py 68
[2, 2, 17]
The code is wrong with 100. It should check case i * i = n:
I think it should be:
while i * i <= n:
if i * i = n:
n = i
break
while n%i == 0:
n = n / i
i = i + 1
print (n)
My code:
# METHOD: PRIME FACTORS
def prime_factors(n):
'''PRIME FACTORS: generates a list of prime factors for the number given
RETURNS: number(being factored), list(prime factors), count(how many loops to find factors, for optimization)
'''
num = n #number at the end
count = 0 #optimization (to count iterations)
index = 0 #index (to test)
t = [2, 3, 5, 7] #list (to test)
f = [] #prime factors list
while t[index] ** 2 <= n:
count += 1 #increment (how many loops to find factors)
if len(t) == (index + 1):
t.append(t[-2] + 6) #extend test list (as much as needed) [2, 3, 5, 7, 11, 13...]
if n % t[index]: #if 0 does else (otherwise increments, or try next t[index])
index += 1 #increment index
else:
n = n // t[index] #drop max number we are testing... (this should drastically shorten the loops)
f.append(t[index]) #append factor to list
if n > 1:
f.append(n) #add last factor...
return num, f, f'count optimization: {count}'
Which I compared to the code with the most votes, which was very fast
def prime_factors2(n):
i = 2
factors = []
count = 0 #added to test optimization
while i * i <= n:
count += 1 #added to test optimization
if n % i:
i += 1
else:
n //= i
factors.append(i)
if n > 1:
factors.append(n)
return factors, f'count: {count}' #print with (count added)
TESTING, (note, I added a COUNT in each loop to test the optimization)
# >>> prime_factors2(600851475143)
# ([71, 839, 1471, 6857], 'count: 1472')
# >>> prime_factors(600851475143)
# (600851475143, [71, 839, 1471, 6857], 'count optimization: 494')
I figure this code could be modified easily to get the (largest factor) or whatever else is needed. I'm open to any questions, my goal is to improve this much more as well for larger primes and factors.
In case you want to use numpy here's a way to create an array of all primes not greater than n:
[ i for i in np.arange(2,n+1) if 0 not in np.array([i] * (i-2) ) % np.arange(2,i)]
Check this out, it might help you a bit in your understanding.
#program to find the prime factors of a given number
import sympy as smp
try:
number = int(input('Enter a number : '))
except(ValueError) :
print('Please enter an integer !')
num = number
prime_factors = []
if smp.isprime(number) :
prime_factors.append(number)
else :
for i in range(2, int(number/2) + 1) :
"""while figuring out prime factors of a given number, n
keep in mind that a number can itself be prime or if not,
then all its prime factors will be less than or equal to its int(n/2 + 1)"""
if smp.isprime(i) and number % i == 0 :
while(number % i == 0) :
prime_factors.append(i)
number = number / i
print('prime factors of ' + str(num) + ' - ')
for i in prime_factors :
print(i, end = ' ')
This is my python code:
it has a fast check for primes and checks from highest to lowest the prime factors.
You have to stop if no new numbers came out. (Any ideas on this?)
import math
def is_prime_v3(n):
""" Return 'true' if n is a prime number, 'False' otherwise """
if n == 1:
return False
if n > 2 and n % 2 == 0:
return False
max_divisor = math.floor(math.sqrt(n))
for d in range(3, 1 + max_divisor, 2):
if n % d == 0:
return False
return True
number = <Number>
for i in range(1,math.floor(number/2)):
if is_prime_v3(i):
if number % i == 0:
print("Found: {} with factor {}".format(number / i, i))
The answer for the initial question arrives in a fraction of a second.
Below are two ways to generate prime factors of given number efficiently:
from math import sqrt
def prime_factors(num):
'''
This function collectes all prime factors of given number and prints them.
'''
prime_factors_list = []
while num % 2 == 0:
prime_factors_list.append(2)
num /= 2
for i in range(3, int(sqrt(num))+1, 2):
if num % i == 0:
prime_factors_list.append(i)
num /= i
if num > 2:
prime_factors_list.append(int(num))
print(sorted(prime_factors_list))
val = int(input('Enter number:'))
prime_factors(val)
def prime_factors_generator(num):
'''
This function creates a generator for prime factors of given number and generates the factors until user asks for them.
It handles StopIteration if generator exhausted.
'''
while num % 2 == 0:
yield 2
num /= 2
for i in range(3, int(sqrt(num))+1, 2):
if num % i == 0:
yield i
num /= i
if num > 2:
yield int(num)
val = int(input('Enter number:'))
prime_gen = prime_factors_generator(val)
while True:
try:
print(next(prime_gen))
except StopIteration:
print('Generator exhausted...')
break
else:
flag = input('Do you want next prime factor ? "y" or "n":')
if flag == 'y':
continue
elif flag == 'n':
break
else:
print('Please try again and enter a correct choice i.e. either y or n')
Since nobody has been trying to hack this with old nice reduce method, I'm going to take this occupation. This method isn't flexible for problems like this because it performs loop of repeated actions over array of arguments and there's no way how to interrupt this loop by default. The door open after we have implemented our own interupted reduce for interrupted loops like this:
from functools import reduce
def inner_func(func, cond, x, y):
res = func(x, y)
if not cond(res):
raise StopIteration(x, y)
return res
def ireducewhile(func, cond, iterable):
# generates intermediary results of args while reducing
iterable = iter(iterable)
x = next(iterable)
yield x
for y in iterable:
try:
x = inner_func(func, cond, x, y)
except StopIteration:
break
yield x
After that we are able to use some func that is the same as an input of standard Python reduce method. Let this func be defined in a following way:
def division(c):
num, start = c
for i in range(start, int(num**0.5)+1):
if num % i == 0:
return (num//i, i)
return None
Assuming we want to factor a number 600851475143, an expected output of this function after repeated use of this function should be this:
(600851475143, 2) -> (8462696833 -> 71), (10086647 -> 839), (6857, 1471) -> None
The first item of tuple is a number that division method takes and tries to divide by the smallest divisor starting from second item and finishing with square root of this number. If no divisor exists, None is returned.
Now we need to start with iterator defined like this:
def gener(prime):
# returns and infinite generator (600851475143, 2), 0, 0, 0...
yield (prime, 2)
while True:
yield 0
Finally, the result of looping is:
result = list(ireducewhile(lambda x,y: div(x), lambda x: x is not None, iterable=gen(600851475143)))
#result: [(600851475143, 2), (8462696833, 71), (10086647, 839), (6857, 1471)]
And outputting prime divisors can be captured by:
if len(result) == 1: output = result[0][0]
else: output = list(map(lambda x: x[1], result[1:]))+[result[-1][0]]
#output: [2, 71, 839, 1471]
Note:
In order to make it more efficient, you might like to use pregenerated primes that lies in specific range instead of all the values of this range.
You shouldn't loop till the square root of the number! It may be right some times, but not always!
Largest prime factor of 10 is 5, which is bigger than the sqrt(10) (3.16, aprox).
Largest prime factor of 33 is 11, which is bigger than the sqrt(33) (5.5,74, aprox).
You're confusing this with the propriety which states that, if a number has a prime factor bigger than its sqrt, it has to have at least another one other prime factor smaller than its sqrt. So, with you want to test if a number is prime, you only need to test till its sqrt.
def prime(n):
for i in range(2,n):
if n%i==0:
return False
return True
def primefactors():
m=int(input('enter the number:'))
for i in range(2,m):
if (prime(i)):
if m%i==0:
print(i)
return print('end of it')
primefactors()
Another way that skips even numbers after 2 is handled:
def prime_factors(n):
factors = []
d = 2
step = 1
while d*d <= n:
while n>1:
while n%d == 0:
factors.append(d)
n = n/d
d += step
step = 2
return factors
I have a solution to a problem that uses dynamic programming. I need help turning this from a recursive solution into an iterative one.
The function takes in a number and follows the three rules:
it may divide the number in half
it may subtract one
it may add one
until the number is 1. My goal is to find the minimum number of steps it takes to do this.
Here is my solution:
def solution(n):
n = int(n)
memo = {}
return memoized_fuel_injection_perfection(n, memo)
def memoized_fuel_injection_perfection(n, memo):
if n == 1:
return 0
if n == 2:
return 1
if n in memo:
return memo[n]
if n % 2 == 0:
if n not in memo:
memo[n] = memoized_fuel_injection_perfection(n//2, memo) + 1
return memo[n]
return min(memoized_fuel_injection_perfection(n-1, memo), memoized_fuel_injection_perfection(n+1, memo)) + 1
But when I input numbers larger than 300 digits long, I am getting a recursive error. How can I turn this into an iterative solution? Any help or guidance is appreciated.
Here is an iterative solution I created, but I am getting MemoryError with very large inputs. Is there some way I can optimize storing the variables so I don't have to compute them for every number?
def solution(n):
memo = {}
memo[0] = 0
memo[1] = 0
memo[2] = 1
n = int(n)
for i in range(3, n+1):
if i % 2 == 0:
memo[i] = memo[i//2] + 1
else:
memo[i] = min(memo[i//2], memo[i//2 + 1]) + 2
return memo[n]
The problem you said you're having with writing an iterative solution is the use of memoized_fuel_injection_perfection(n+1, memo), which makes it tricky to determine what order to compute results in. The key is that you cannot repeatedly go down this code path indefinitely. If you could, even your recursive solution would be invalid.
Immediately after a +1 or -1 operation, you always perform a divide-by-2. We can fuse the +1 or -1 with the divide-by-2, producing an operation that cannot increase the number. The core of an iterative solution would then look like this:
if n % 2 == 0:
table[n] = table[n//2] + 1
else:
table[n] = min(table[n//2], table[n//2+1]) + 2
Can you complete things from there? (You'll need a way to avoid computing results for every positive integer less than n.)
Here's my attempt:
def solution(n):
def is_even(n): # helper function
return n % 2 == 0
possible_nodes = {1} # 1 is the destination
consider = [n] # stack: numbers to be considered
while consider: # as long as non-empty
x = consider.pop() # now think about where can we move from x
if x in possible_nodes: # if it is already handled before
continue
if is_even(x): # if even, we just halve it
consider.append(x//2)
else: # otherwise, -1 or +1
consider += [x-1, x+1]
possible_nodes.add(x) # mark x as 'considered'
steps = {1: 0} # dict to store min steps
for x in filter(is_even, sorted(possible_nodes)): # odds calculated only when needed
if x//2 not in steps: # if x//2 was not computed, x//2 must be odd
steps[x//2] = min(steps[x//2 - 1], steps[x//2 + 1]) + 1
steps[x] = steps[x//2] + 1
return steps[n] if is_even(n) or n == 1 else min(steps[n-1], steps[n+1]) + 1
n = 10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003333000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003483983333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333
print(solution(n)) # 2467
print(*(solution(i) for i in range(1, 21)))
# 0 1 2 2 3 3 4 3 4 4 5 4 5 5 5 4 5 5 6 5
The code basically consists of two steps. In the first step, it enumerates all the possible steps from n, under the rule that for x,
if x is even, we only consider x//2 as the next step; this strategy is adopted also in your code;
if x is odd, we consider x-1 and x+1 as the next step.
I did this because calculating the minimum steps for all values up to n is wasteful. (Actually at first I tried to do so by initiating something like [None] * n, but it seems like python cannot handle such a long list. Even if it can, I guess that would be extremely slow.)
The next step is calculating the minimum steps, starting from the smallest number. I address the problem of accessingsteps[x+1] by "not calculating steps[x] for odd x eagerly." We only calculate steps[x] for even x eagerly, but lazily for odd x.
The rationale is the following; by the time odd x is needed, it must be the case that x is either k//2 - 1 or k//2 + 1 for some even k, which must be larger than x + 1. Since x + 1 is even, step[x+1] must have been already calculated, by the construction of the for loop.
This is my solution to Project Euler Problem 3. I have written this code for Project Euler but if I put in "49" i get "49". What seems to be the problem?
n = 600851475143
i = 2
while (i * i < n):
while (n % i == 0):
n = n / i
i = i + 1
print (n)
I'm assuming you meant set n = 49.
Your outer while loop checks the condition i * i < n, which is not true for i == 7, so the outer loop breaks as soon as it hits 7. Change the < to <=.
However, your code isn't correct in the first place-- perhaps something like this is what you meant?
n = 600851475143
i = 2
factors = []
while (i <= n):
while (n % i == 0):
n = n / i
factors.append(i)
i = i + 1
print factors
You're printing n you want to print i...
Probably the fastest way to solve it by finding all the prime factors and then return the max.
Brute force solution took me less then 1 sec
I'm assuming you mean n = 49.
Your code isn't right, but the error is small -- change the < to <= and it works for Project Euler #3.
The problem of the code not working for squares such as 49 still remains though. Here is a modified piece of code that should work for squares as well.
n = 49
i = 2
while i * i <= n:
while n % i == 0:
x = n
n = n / i
i = i + 1
if n == 1:
print x
else:
print n
finding factors of N only need to check upto √N.
First basic solution:-
value of N never change
find factors upto √N & store biggest factor.
from math import sqrt
ans = -1
n = input() #or directly put
for i in range(2,int(sqrt(n))+1):
while (n%i==0):
if i > ans:
ans = i
print(ans)
Little optimized solution:-
if we change value of N, it iterate less than previous method.
only need to check % (modulus) of N with primes.
if have prime numbers list, then check/iterate with that only
unless, ignoring even numbers check numbers like 9,15,21... is prime or not, is worthless so...
excluding 2 all prime is odd.
so after check N with 2, check N with only odd numbers.
find factors upto √N & store biggest factor.
when get factor, divide N until N no have that factor
find the next factor do same process, until N become 1 (no have any factors)
from math import sqrt
ans = 2
n = input() #or directly put
while (n%2 == 0):
n /= 2
i = 3
while n > 1:
while (n%i == 0):
ans = i
n /= i
i += 2
print(ans)
find prime factors and return largest obviously
from math import sqrt
def is_prime(n):
if n ==2:return True
if n<2:return False
if n%2==0:return False
for i in range(3,int(sqrt(n))+1,2):
if n%i == 0:
return False;
return True;
n = 600851475143
i = n
while(i>1):
if is_prime(i) and is_prime(i) and n%i==0:
print(i);
break
i = i-1;
Your code is written assuming there are more than one factor, but in the case of n=49, it turns out that it has only one factor that is 7. So you can add a line checking whether it has more than one factor, or if not then it should be printed.
I am trying to solve the problem mentioned here: https://www.spoj.pl/problems/PRIME1/
I am also giving the description below.
Peter wants to generate some prime numbers for his cryptosystem. Help him! Your task is to generate all prime numbers between two given numbers!
Input
The input begins with the number t of test cases in a single line (t<=10). In each of the next t lines there are two numbers m and n (1 <= m <= n <= 1000000000, n-m<=100000) separated by a space.
Output
For every test case print all prime numbers p such that m <= p <= n, one number per line, test cases separated by an empty line.`
My code is as below. I am thinking remove method on list is very slow.
import sys
import math
num = int(sys.stdin.readline());
indices = []
maxrange = 2
while(num > 0):
a,b = sys.stdin.readline().split(" ");
a = int(a)
b = int(b)
if(a < 2):
a = 2
indices.append((a,b))
if(b > maxrange):
maxrange= b
num = num - 1
val = int(math.sqrt(maxrange)+1)
val2 = int(math.sqrt(val)+1)
checks = range(2,val2)
for i in range(2,val2):
for j in checks:
if(i!= j and j%i == 0):
checks.remove(j)
primes = range(2,val)
for i in checks:
for j in primes:
if(i != j and j%i == 0):
primes.remove(j)
primes2 = range(2,maxrange)
for i in primes:
for j in primes2:
if(j != i and j%i == 0):
primes2.remove(j)
for (a,b) in indices:
for p in primes2:
if(a<= p and b >= p):
print p
if(p > b):
break
print
I think python list remove is very slow. My code is correct but I am getting timelimit exceeded. can someone help me improve this code.
A primality testing function will perform best. There's pseudocode on the Miller-Rabin wikipedia page
Instead of removing the element that is not a prime, why not replace it with some sentinel value, perhaps -1 or None? Then when printing, just print the values that aren't sentinels.
Use a list of length (n-m), and then the index for number i is x[m+i].
remove() isn't slow in the grand scheme of things, it's just that the code calls it a LOT.
As dappawit suggests, rather than modifying the list, change the value in the list so you know that it isn't a valid number to use.
I also see that when you generate the set of prime numbers, you use range(2,maxrange) which is okay, but not efficient if the lower bound is much greater than 2. You'll be wasting computing time on generating primes that aren't even relevant to the problem space. If nothing else, keep track of minrange as well as maxrange.
A bug with your original code is that you use range(2,maxrange). That means maxrange is not in the list of numbers considered. Try 3 5 as input for a and b to see the bug.
range(2,maxrange+1) fixes the problem.
Another bug in the code is that you modify the original sequence:
From Python docs - for-statement
It is not safe to modify the sequence being iterated over in the loop (this can only happen for mutable sequence types, such as lists). If you need to modify the list you are iterating over (for example, to duplicate selected items) you must iterate over a copy. The slice notation makes this particularly convenient:
My python skills are rudimentary, but this seems to work:
Old:
primes2 = range(2,maxrange)
for i in primes:
for j in primes2:
if(j != i and j%i == 0):
primes2.remove(j)
for (a,b) in indices:
for p in primes2:
if(a<= p and b >= p):
New:
primes2 = array.array('L', range(minrange,maxrange+1))
for i in primes:
for j in primes2:
if(j != i and j%i == 0):
primes2[j-minrange] = 0
for (a,b) in indices:
for p in primes2:
if (p != 0):
if(a<= p and b >= p):
You could also skip generating the set of prime numbers and just test the numbers directly, which would work if the sets of numbers you have to generate prime numbers are not overlapping (no work duplication).
enter link description here
Here's a deterministic variant of the Miller–Rabin primality test for small odd integers in Python:
from math import log
def isprime(n):
assert 1 < n < 4759123141 and n % 2 != 0, n
# (n-1) == 2**s * d
s = 0
d = n-1
while d & 1 == 0:
s += 1
d >>= 1
assert d % 2 != 0 and (n-1) == d*2**s
for a in [2, 7, 61]:
if not 2 <= a <= min(n-1, int(2*log(n)**2)):
break
if (pow(a, d, n) != 1 and
all(pow(a, d*2**r, n) != (n-1) for r in xrange(s))):
return False
return True
The code intent is to be an executable pseudo-code.