Index out of range error sieving B-smooth numbers with logarithms - python

So I have been trying to implement the quadratic sieve and I did step 1 which is(in code):
f = 44
b = ceil(sqrt(n))
factorBase = [i for i in genPrimes(f) if jacobi(n, i) == 1]
t = [modInverse(n, p) for p in factorBase]
sol1 = [(t[i] - b) % factorBase[i] for i in range(len(t))]
sol2 = [(-t[i] - b) % factorBase[i] for i in range(len(t))]
l = [ln(p) for p in factorBase]
size = 60
Here genPrimes() is Sieve of Eratosthenes, jacobi checks if n is quadratic residue mod i, and modInverse is Tonelli-Shanks algorithm.
The next step in the quadratic sieve is this:
Initialize a sieve array to 0's. For each odd prime p in the factor
base, add l[p] to the locations sol1[p] + ip and soln[p] + ip of the sieve array, for
i = 0, 1, 2,... For the prime p = 2, sieve only with sol1.
Or as explained here:
Then I have to add values from 𝑙𝑝 to sieving array to positions π‘ π‘œπ‘™1[𝑗]+π‘–βˆ—factor_base[j] and
π‘ π‘œπ‘™1[𝑗]+π‘–βˆ— factor_base[j], where 0≀𝑖≀ size and 0≀𝑗≀|factor_base|. And for prime 𝑝=2 add 𝑙𝑝 only to
positions with sol1.
Now say these were my lists:
sieveArray = [0 for i in range(60)]
factorBase = [2,3,7,17,23,29,37,41]
sol1 = [0,0,2,13,11,26,10,28]
sol2 = [0,1,5,14,8,10,17,26]
l = [0.69,1.1,1.95,2.83,3.14,3.37,3.61,3.71] # logs of factorbase rounded to 2 decimals
I should, following what was said above get this new list:
sieveArray = [1.79,1.1,2.64,1.1,1.79,1.95,1.79,1.1,3.83,3.05,8.77,3.14,3.74,3.93,3.52,1.1,3.74,3.61,1.79,3.0
5,0.69,1.1,1.79,1.95,1.79,1.1,9.72,1.1,5.5,0.0,6.57,7.07,0.69,3.05,4.93,0.0,1.79,3.05,0.69,4.47
,3.74,0.0,1.79,1.1,2.64,1.1,1.79,8.39,4.62,1.1,0.69,3.05,1.79,0.0,10.49,4.47,0.69,4.24,3.74,0.0]
However whenever I try to program I mess up horribly and index out of range errors. Here is my failed code:
for j in factorBase:
if j != 2:
for i in range(0, size):
try:
sieveArray[sol1[j] + (i * factorBase[j])] += l[j]
sieveArray[sol2[j] + (i * factorBase[j])] += l[j]
except:
continue
#Didn't implement case for 2 since I didn't know what I was doing.
Can someone please explain to me what I am doing wrong and how I can get expected results. Also If you want the actual explanation on what the step is go to https://pdfs.semanticscholar.org/5c52/8a975c1405bd35c65993abf5a4edb667c1db.pdf page 6(qs algorithm) step 2 or https://math.stackexchange.com/questions/183183/quadratic-sieve-algorithm?rq=1.
Error when there are no try-except statements:
sieveArray[sol1[j] + (i * factorBase[j])] += j
IndexError: list index out of range
Note: No Index Out of Range error because of the try-except but the code doesn't work properly at all still.

Related

Passing big arguments in change-making problem

I have problem with change-making problem algorithm.
My function coin_change_solutions works well with small numbers.
For example if we pass [1,10,25] as coins and 32 as S (change that we want to get) it will return [10,10,10,1,1]. Problem occurs when I want to pass bigger numbers as I want to operate on cents, not on dollars so that I have fixed-point arithmetic (it's a must because operating on floating-point arithmetic won't be a good idea later on).
So when I pass an array with all the denominations in cents [1,5,10,25,50,100,200,500,1000,2000,10000,50000] and 50000 as change my compiler stops and doesn't show any result.
Do you know what should I do so that the algorithm has high efficiency and can be passed all the nominals in cents?
def coin_change_solutions(coins, S):
# create an S x N table for memoization
N = len(coins)
sols = [[[] for n in range(N + 1)] for s in range(S + 1)]
for n in range(0, N + 1):
sols[0][n].append([])
# fill table using bottom-up dynamic programming
for s in range(1, S+1):
for n in range(1, N+1):
without_last = sols[s][n - 1]
if (coins[n - 1] <= s):
with_last = [list(sol) + [coins[n-1]] for sol in sols[s - coins[n - 1]][n]]
else:
with_last = []
sols[s][n] = without_last + with_last
x = min(sols[S][N], key=len)
return x
Not the solution to your query, but a better solution with less space:
dp = [0] + [float('inf') for i in range(S)]
for i in range(1, S+1):
for coin in coins:
if i - coin >= 0:
dp[i] = min(dp[i], dp[i-coin] + 1)
if dp[-1] == float('inf'):
return -1
return dp[-1]
Assume dp[i] is the fewest number of coins making up amount S, then for every coin in coins, dp[i] = min(dp[i - coin] + 1).
The time complexity is O(amount * coins.length) and the space complexity is O(amount).

Trying to define one of Euler's approximations to pi, getting unsupported operand type(s) for 'list and 'int'

I am trying to define a function which will approximate pi in python using one of Euler's methods. His formula is as follows:
My code so far is this:
def pi_euler1(n):
numerator = list(range(2 , n))
for i in numerator:
j = 2
while i * j <= numerator[-1]:
if i * j in numerator:
numerator.remove(i * j)
j += 1
for k in numerator:
if (k + 1) % 4 == 0:
denominator = k + 1
else:
denominator = k - 1
#Because all primes are odd, both numbers inbetween them are divisible by 2,
#and by extension 1 of the 2 numbers is divisible by 4
term = numerator / denominator
I know this is wrong, and also incomplete. I'm just not quite sure what the TypeError that I mentioned earlier actually means. I'm just quite stuck with it, I want to create a list of the terms and then find their products. Am I on the right lines?
Update:
I have worked ways around this, fixing the clearly obvious errors that were prevalent thanks to msconi and Johanc, now with the following code:
import math
def pi_euler1(n):
numerator = list(range(2 , 13 + math.ceil(n*(math.log(n)+math.log(math.log(n))))))
denominator=[]
for i in numerator:
j = 2
while i * j <= numerator[-1]:
if (i * j) in numerator:
numerator.remove(i * j)
j += 1
numerator.remove(2)
for k in numerator:
if (k + 1) % 4 == 0:
denominator.append(k+1)
else:
denominator.append(k-1)
a=1
for i in range(n):
a *= numerator[i] / denominator[i]
return 4*a
This seems to work, when I tried to plot a graph of the errors from pi in a semilogy axes scale, I was getting a domain error, but i needed to change the upper bound of the range to n+1 because log(0) is undefined. Thank you guys
Here is the code with some small modifications to get it working:
import math
def pi_euler1(n):
lim = n * n + 4
numerator = list(range(3, lim, 2))
for i in numerator:
j = 3
while i * j <= numerator[-1]:
if i * j in numerator:
numerator.remove(i * j)
j += 2
euler_product = 1
for k in numerator[:n]:
if (k + 1) % 4 == 0:
denominator = k + 1
else:
denominator = k - 1
factor = k / denominator
euler_product *= factor
return euler_product * 4
print(pi_euler1(3))
print(pi_euler1(10000))
print(math.pi)
Output:
3.28125
3.148427801913721
3.141592653589793
Remarks:
You only want the odd primes, so you can start with a list of odd numbers.
j can start with 3 and increment in steps of 2. In fact, j can start at i because all the multiples of i smaller than i*i are already removed earlier.
In general it is very bad practise to remove elements from the list over which you are iterating. See e.g. this post. Internally, Python uses an index into the list over which it iterates. Coincidently, this is not a problem in this specific case, because only numbers larger than the current are removed.
Also, removing elements from a very long list is very slow, as each time the complete list needs to be moved to fill the gap. Therefore, it is better to work with two separate lists.
You didn't calculate the resulting product, nor did you return it.
As you notice, this formula converges very slowly.
As mentioned in the comments, the previous version interpreted n as the limit for highest prime, while in fact n should be the number of primes. I adapted the code to rectify that. In the above version with a crude limit; the version below tries a tighter approximation for the limit.
Here is a reworked version, without removing from the list you're iterating. Instead of removing elements, it just marks them. This is much faster, so a larger n can be used in a reasonable time:
import math
def pi_euler_v3(n):
if n < 3:
lim = 6
else:
lim = n*n
while lim / math.log(lim) / 2 > n:
lim //= 2
print(n, lim)
numerator = list(range(3, lim, 2))
odd_primes = []
for i in numerator:
if i is not None:
odd_primes.append(i)
if len(odd_primes) >= n:
break
j = i
while i * j < lim:
numerator[(i*j-3) // 2] = None
j += 2
if len(odd_primes) != n:
print(f"Wrong limit calculation, only {len(odd_primes)} primes instead of {n}")
euler_product = 1
for k in odd_primes:
denominator = k + 1 if k % 4 == 3 else k - 1
euler_product *= k / denominator
return euler_product * 4
print(pi_euler_v2(100000))
print(math.pi)
Output:
3.141752253548891
3.141592653589793
In term = numerator / denominator you are dividing a list by a number, which doesn't make sense. Divide k by the denominator in the loop in order to use the numerator element for each of the equation's factors one by one. Then you could multiply them repeatedly to the term term *= i / denominator, which you initialize in the beginning as term = 1.
Another issue is the first loop, which won't give you the first n prime numbers. For example, for n=3, list(range(2 , n)) = [2]. Therefore, the only prime you will get is 2.

Circular Array Rotation: Python 2.7

I am trying to implement a circular rotation algorithm for a hackerrank challenge question. My code(middle block) seems to run fine for small inputs but fails for larger inputs due to timeout. Any help optimizing the code will be much appreciated.
Here is my code:
import sys
n,k,q = raw_input().strip().split(' ')
n,k,q = [int(n),int(k),int(q)]
a = map(int,raw_input().strip().split(' '))
for j in range(0,k):
temp = a[n-1]
for i in range(n-2, -1, -1):
a[i+1] = a[i]
a[0] = temp
for a0 in xrange(q):
m = int(raw_input().strip())
print a[m]
You don't have to actually rotate the array to find the item but you can use modulo calculus to do that.
If we have index i and we move it k places his new index will be m=(i+k)%n so if we have an index m that has been moved k places then it's previous location was i=(m-k)%n, but since we have to handle it becoming negative if k > m we add len(a), python handles this but in general it's the more complete answer.
Knowing that we can write the following:
for a0 in xrange(q):
m = int(raw_input().strip())
prev_index = (len(a) + m - k) % n
print a[prev_index]

An Explanation for the totient finder in this program

I need an explanation for the program suggested in the edit in the first answer over here. It is a program to find the totients of a range of numbers. Can somebody provide a simple explanation? (Ignore the summation part for now, I need to find out how the init method finds the totients.) I know there is an explanation in the answer, but that is an explanation for different programs, I need an explanation for this particular one.
class Totient:
def __init__(self, n):
self.totients = [1 for i in range(n)]
for i in range(2, n):
if self.totients[i] == 1:
for j in range(i, n, i):
self.totients[j] *= i - 1
k = j / i
while k % i == 0:
self.totients[j] *= i
k /= i
def __call__(self, i):
return self.totients[i]
if __name__ == '__main__':
from itertools import imap
totient = Totient(10000)
print sum(imap(totient, range(10000)))
It's a variant of the Sieve of Eratosthenes for finding prime numbers.
If you want to know the totient of a single number n, the best way to find it is to factor n and take the product of 1 less than each factor; for instance, 30 = 2 * 3 * 5, and subtracting 1 from each factor, then multiplying, gives the totient 1 * 2 * 4 = 8. But if you want to find the totients of all the numbers less than a given n, a better approach than factoring each of them is sieving. The idea is simple: Set up an array X from 0 to n, store i in each Xi, then run through the array starting from 0 and whenever Xi = i loop over the multiples of i, multiplying each by i βˆ’ 1.
Further discussion and code at my blog.
I'm not completely sure what the code is doing -- but frankly it looks pretty bad. It clearly is trying to use that Euler's totient function is multiplicative, meaning that a,b are relatively prime then t(a,b) = t(a)*t(b), together with the fact that if p is a prime then t(p) = p-1. But -- it seems to be using crude trial division to determine such things. If you really want to calculate the totient of all numbers in a given range then you should use an algorithm that sieves the numbers as you go along.
Here is a version which sieves as it goes and exploits the multiplicative nature to the hilt. At each pass through the main loop it starts with a prime, p which hasn't yet been processed. It determines all powers of p <= n and then uses a direct formula for these powers (see https://en.wikipedia.org/wiki/Euler%27s_totient_function ). Once these totients have been added, it forms all possible products <= n of these powers and the numbers for which the totients have been previously computed. This gives a whole slew of numbers to add to the list of previously determined numbers. At most sqrt(n) passes need to be made through the main loop. It runs almost instantly for n = 10000. It returns a list where the ith value is the totient of i (with t(0) = 0 for convenience):
def allTotients(n):
totients = [None]*(n+1) #totients[i] will contain the t(i)
totients[0] = 0
totients[1] = 1
knownTotients = [] #known in range 2 to n
p = 2
while len(knownTotients) < n - 1:
powers = [p]
k = 2
while p ** k <= n:
powers.append(p ** k)
k +=1
totients[p] = p - 1
for i in range(1,len(powers)):
totients[powers[i]] = powers[i] - powers[i-1]
#at this stage powers represent newly discovered totients
#combine with previously discovered totients to get still more
newTotients = powers[:]
for m in knownTotients:
for pk in powers:
if m*pk > n: break
totients[m*pk] = totients[m]*totients[pk]
newTotients.append(m*pk)
knownTotients.extend(newTotients)
#if there are any unkown totients -- the smallest such will be prime
if len(knownTotients) < n-1:
p = totients.index(None)
return totients
For completeness sake, here is a Python implementation of the algorithm to compute the totient of a single number which user448810 described in their answer:
from math import sqrt
#crude factoring algorithm:
small_primes = [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]
def factor(n):
#returns a list of prime factors
factors = []
num = n
#first pull out small prime factors
for p in small_primes:
while num % p == 0:
factors.append(p)
num = num // p
if num == 1: return factors
#now do trial division, starting at 101
k = 101
while k <= sqrt(num):
while num % k == 0:
factors.append(k)
num = num // k
k += 2
if num == 1:
return factors
else:
factors.append(num)
return factors
def totient(n):
factors = factor(n)
unique_factors = set()
t = 1
for p in factors:
if p in unique_factors:
t *= p
else:
unique_factors.add(p)
t *= (p-1)
return t

Number of numbers divisible by a prime number in a row to pascal triangle

How can i find the total number of numbers in a given row number of a pascal triangle divisible by a prime number in which the row number and prime is given
I am using the following code in python
def factorial(x):
result = 1
for i in xrange(1,x+1):
result *= i
return result
def combination(n,r):
return factorial(n)/(factorial(n-r)*factorial(r))
p = input()
cnt = 0
for i in range(0,n+1):
if((combination(n,i)%p)==0):
cnt += 1
print cnt
but the given code takes long time for big numbers.
Can you please suggest me a better algorithm.
One corollary from Luca's theorem states that number of binomial coefficients C(n,k) which are not divisible by prime p, is
(a₁+1)β‹…(aβ‚‚+1)β‹…...β‹…(am+1), where ai is ith digit of n in p-ary numeral system.
Example:
p = 3, n = 7dec = 213
Result = (2+1)β‹…(1+1) = 6
7th row of Pascal triangle is 1 7 21 35 35 21 7 1, it contains 6 coefficients not divisible by 3, and the two remaining are divisible by 3.
You do not need to compute the binomial coefficient (n,r).
Count how often p is in n!, r! and (n-r)! and check if n! has more factors p than the other two togeter.
// sry... no python...
long count_p_in_fac(long n, long p)
{
long count = 0;
long i = 1;
long temp;
while(true)
{
temp = floor(n/pow(p,i));
count += temp;
if(temp == 0)
break;
}
return count;
}
p = input()
cnt = 0
for i in range(0,n+1):
if(count_p_in_fac(n,p) > count_p_in_fac(i,p) + count_p_in_fac(n-i,p)):
cnt += 1
print cnt
This avoids big numbers and reduces the operations.
This checks (n,r) = 0 mod p in O(log(n)) without computing factorials. But counting a row takes O(n log n).
You can also speed this up by using the symmetry of (n,r). Computing only the first half and multiply it by two. If n is even, you have to count the first half exept the middle r = n/2 and check add the middle after multiply by two.
And you can precompute count_p_in_fac(i,p) for all i.
There's no way you're going to do 10^12 in less than a second. There has to be some property of Pascall's Triangle that makes this easier.. If it's possible
Another interesting property of Pascal's triangle is that in a row p
where p is a prime number, all the terms in that row except the 1s are
multiples of p. This can be proven easily, since if p\in \mathbb{P},
then p has no factors save for 1 and itself. Every entry in the
triangle is an integer, so therefore by definition (p-k)! and k! are
factors of p!\,. However, there is no possible way p itself can show
up in the denominator, so therefore p (or some multiple of it) must be
left in the numerator, making the entire entry a multiple of p.
It might have something to do with that result (from the wiki page http://en.wikipedia.org/wiki/Pascal%27s_triangle).. if this has an answer (i.e. if it's university homework some professor gave you).
See here https://mathoverflow.net/questions/9181/pascal-triangle-and-prime-numbers
(I love this question - I'm not sure it's a programming question though).
You can rewrite your combination function without needing to calculate factorial. (n, r) can be written recursively as
(n, r) = (n-1, r) + (n-1, r-1)
Now we should find the base cases. These are:
(n, 1) = n
(n, 0) = 1
(n, n) = 1
Here, we are assuming that n and r are non-negative integers and n >= r holds true. Then the function combination can be rewritten as
def combination(n, r):
if r == 1:
return n
if r == 0 or r == n:
return 1
return combination(n-1, r) + combination(n-1, r-1)
p = input()
count = 0
for i in range(n + 1):
if combination(n, i) % p == 0:
count += 1
print count
Thank you all for responding to the question of a noob like me
Here is a working python code
n,p = map(int,raw_input().split(' '))
if n==p:
print n-1
elif p>n:
print 0
else:
result = 1
m = n
while n:
temp = n%p
result *= (temp+1)
n /= p
print m+1-result
n = input("enter the row for pascal triangle:")
p = input("enter any prime number u want:")
cnt = 0
line = [1]
for k in range(0, n):
line.append(line[k] * (n-k) / (k+1))
print line
lengths = map(lambda word: line[word]%p ==0, range(len(line))).count(True)
print lengths

Categories