Lucas probable prime test - python

I have been trying to implement the Baillie-PSW primality test for a few days, and have ran into some problems. Sepcifically when trying to use the Lucas probable prime test. My question is not about Baile, but on how to generate the correct Lucas sequence modulo some number
For the first two psudoprimes my code gives the correct result, eg for 323 and 377. However for the next psudoprime, both the standard implementation and the doubling version fails.
Trying to do modulo operations on V_1 completely breaks the doubling version of the Luckas sequence generator.
Any tips or suggestions on how to correctly implement the Lucas probable prime test in Python?
from fractions import gcd
from math import log
def luckas_sequence_standard(num, D=0):
if D == 0:
D = smallest_D(num)
P = 1
Q = (1-D)/4
V0 = 2
V1 = P
U0 = 0
U1 = 1
for _ in range(num):
U2 = (P*U1 - Q*U0) % num
U1, U0 = U2, U1
V2 = (P*V1 - Q*V0) % num
V1, V0 = V2, V1
return U2%num, V2%num
def luckas_sequence_doubling(num, D=0):
if D == 0:
D = smallest_D(num)
P = 1
Q = (1 - D)/4
V0 = P
U0 = 1
temp_num = num + 1
double = []
while temp_num > 1:
if temp_num % 2 == 0:
double.append(True)
temp_num //= 2
else:
double.append(False)
temp_num += -1
k = 1
double.reverse()
for is_double in double:
if is_double:
U1 = (U0*V0) % num
V1 = V0**2 - 2*Q**k
U0 = U1
V0 = V1
k *= 2
elif not is_double:
U1 = ((P*U0 + V0)/2) % num
V1 = (D*U0 + P*V0)/2
U0 = U1
V0 = V1
k += 1
return U1%num, V1%num
def jacobi(a, m):
if a in [0, 1]:
return a
elif gcd(a, m) != 1:
return 0
elif a == 2:
if m % 8 in [3, 5]:
return -1
elif m % 8 in [1, 7]:
return 1
if a % 2 == 0:
return jacobi(2,m)*jacobi(a/2, m)
elif a >= m or a < 0:
return jacobi(a % m, m)
elif a % 4 == 3 and m % 4 == 3:
return -jacobi(m, a)
return jacobi(m, a)
def smallest_D(num):
D = 5
k = 1
while k > 0 and jacobi(k*D, num) != -1:
D += 2
k *= -1
return k*D
if __name__ == '__main__':
print luckas_sequence_standard(323)
print luckas_sequence_doubling(323)
print
print luckas_sequence_standard(377)
print luckas_sequence_doubling(377)
print
print luckas_sequence_standard(1159)
print luckas_sequence_doubling(1159)

Here is my Lucas pseudoprimality test; you can run it at ideone.com/57Iayq.
# lucas pseudoprimality test
def gcd(a,b): # euclid's algorithm
if b == 0: return a
return gcd(b, a%b)
def jacobi(a, m):
# assumes a an integer and
# m an odd positive integer
a, t = a % m, 1
while a <> 0:
z = -1 if m % 8 in [3,5] else 1
while a % 2 == 0:
a, t = a / 2, t * z
if a%4 == 3 and m%4 == 3: t = -t
a, m = m % a, a
return t if m == 1 else 0
def selfridge(n):
d, s = 5, 1
while True:
ds = d * s
if gcd(ds, n) > 1:
return ds, 0, 0
if jacobi(ds, n) == -1:
return ds, 1, (1 - ds) / 4
d, s = d + 2, s * -1
def lucasPQ(p, q, m, n):
# nth element of lucas sequence with
# parameters p and q (mod m); ignore
# modulus operation when m is zero
def mod(x):
if m == 0: return x
return x % m
def half(x):
if x % 2 == 1: x = x + m
return mod(x / 2)
un, vn, qn = 1, p, q
u = 0 if n % 2 == 0 else 1
v = 2 if n % 2 == 0 else p
k = 1 if n % 2 == 0 else q
n, d = n // 2, p * p - 4 * q
while n > 0:
u2 = mod(un * vn)
v2 = mod(vn * vn - 2 * qn)
q2 = mod(qn * qn)
n2 = n // 2
if n % 2 == 1:
uu = half(u * v2 + u2 * v)
vv = half(v * v2 + d * u * u2)
u, v, k = uu, vv, k * q2
un, vn, qn, n = u2, v2, q2, n2
return u, v, k
def isLucasPseudoprime(n):
d, p, q = selfridge(n)
if p == 0: return n == d
u, v, k = lucasPQ(p, q, n, n+1)
return u == 0
print isLucasPseudoprime(1159)
Note that 1159 is a known Lucas pseudoprime (A217120).

Related

Is there a way to insert an arbitrary symbol before the Python output value?

I'm calculating the matrix value with Python, but I want to distinguish the value of equtaion, is there a way?
x - y - 2z = 4
2x - y - z = 2
2x +y +4z = 16
I want to make the expression above like this when I print out the matrix from the function I created
1 -1 -2 | 4
2 -1 -1 | 2
2 1 4 | 16
Same as the rref result of this
1 0 0 | 24
0 1 0 | 72
0 0 1 | -26
def showMatrix():
print("\n")
for i in sd:
for j in i:
print(j, end="\t")
print("\n")
def getone(pp):
for i in range(len(sd[0])):
if sd[pp][pp] != 1:
q00 = sd[pp][pp]
for j in range(len(sd[0])):
sd[pp][j] = sd[pp][j] / q00
def getzero(r, c):
for i in range(len(sd[0])):
if sd[r][c] != 0:
q04 = sd[r][c]
for j in range(len(sd[0])):
sd[r][j] = sd[r][j] - ((q04) * sd[c][j])
sd = [
[1, 1, 2, 9],
[2, 4, -3, 1],
[3, 6, -5, 0]
]
showMatrix()
for i in range(len(sd)):
getone(i)
for j in range(len(sd)):
if i != j:
getzero(j, i)
showMatrix()
print("FiNAL result")
showMatrix()
Here is a function which takes a list of 4 numbers and returns a string representing an equation in x,y,z. It handles coefficients which are negative, zero, or +/-1 appropriately:
def make_equation(nums):
coefficients = nums[:3]
variables = 'xyz'
terms = []
for c,v in zip(coefficients,variables):
if c == 0:
continue
elif c == 1:
coef = ''
elif c == -1:
coef = '-'
else:
coef = str(c)
terms.append(coef + v)
s = ' + '.join(terms)
s = s.replace('+ -','- ')
return s + ' = ' + str(nums[3])
Typical example:
make_equation([2,-3,1,6])
With output:
'2x - 3y + z = 6'

How do I create a magic square matrix using python

A basket is given to you in the shape of a matrix. If the size of the matrix is N x N then the range of number of eggs you can put in each slot of the basket is 1 to N2 . You task is to arrange the eggs in the basket such that the sum of each row, column and the diagonal of the matrix remain same
This code is working only for odd numbers but not even numbers.
here's my code that i tried but it didn't work
`
def matrix(n):
m = [[0 for x in range(n)]
for y in range(n)]
i = n / 2
j = n - 1
num = 1
while num <= (n * n):
if i == -1 and j == n:
j = n - 2
i = 0
else:
if j == n:
j = 0
if i < 0:
i = n - 1
if m[int(i)][int(j)]:
j = j - 2
i = i + 1
continue
else:
m[int(i)][int(j)] = num
num = num + 1
j = j + 1
i = i - 1
print ("Sum of eggs in each row or column and diagonal ",n * (n * n + 1) / 2, "\n")
for i in range(0, n):
for j in range(0, n):
print('%2d ' % (m[i][j]),end = '')
if j == n - 1:
print()
n=int(input("Number of rows of matrix:"))
matrix(n)
`
def matrix(n):
m = [[0 for x in range(n)]
for y in range(n)]
i = n / 2
j = n - 1
num = 1
while num <= (n * n):
if i == -1 and j == n:
j = n - 2
i = 0
else:
if j == n:
j = 0
if i < 0:
i = n - 1
if m[int(i)][int(j)]:
j = j - 2
i = i + 1
continue
else:
m[int(i)][int(j)] = num
num = num + 1
j = j + 1
i = i - 1
print ("Sum of eggs in each row or column and diagonal ",n * (n * n + 1) / 2, "\n")
for i in range(0, n):
for j in range(0, n):
print('%2d ' % (m[i][j]),end = '')
if j == n - 1:
print()
n=int(input("Number of rows of matrix:"))
matrix(n)
def forEvenNumber(n):
arr = [[(n * y) + x + 1 for x in range(n)] for y in range(n)]
for i in range(0, n // 4):
for j in range(0, n // 4):
arr[i][j] = (n * n + 1) - arr[i][j];
for i in range(0, n // 4):
for j in range(3 * (n // 4), n):
arr[i][j] = (n * n + 1) - arr[i][j];
for i in range(3 * (n // 4), n):
for j in range(0, n // 4):
arr[i][j] = (n * n + 1) - arr[i][j];
for i in range(3 * (n // 4), n):
for j in range(3 * (n // 4), n):
arr[i][j] = (n * n + 1) - arr[i][j];
for i in range(n // 4, 3 * (n // 4)):
for j in range(n // 4, 3 * (n // 4)):
arr[i][j] = (n * n + 1) - arr[i][j];
print("\nSum of all row, column and diagonals = ",
n * (n * n + 1) // 2, "\n")
for i in range(n):
for j in range(n):
print('%2d ' % (arr[i][j]), end=" ")
print()
def forOddNumber(n):
mgsqr = [[0 for x in range(n)]
for y in range(n)]
r = n // 2
c = n - 1
num = 1
while num <= (n * n):
if r == -1 and c == n:
c = n - 2
r = 0
else:
if c == n:
c = 0
if r < 0:
r = n - 1
if mgsqr[int(r)][int(c)]:
c = c - 2
r = r + 1
continue
else:
mgsqr[int(r)][int(c)] = num
num = num + 1
c = c + 1
r = r - 1
print("\nSum of all row, column and diagonals = ",
n * (n * n + 1) // 2, "\n")
for i in range(0, n):
for j in range(0, n):
print('%2d ' % (mgsqr[i][j]), end='')
print()
print("\nWELCOME:)\n")
n = int(input("Please Enter Number of Rows and Column (n*n): "))
if n%2==0:
forEvenNumber(n)
else:
forOddNumber(n)
print("\nThank You :)")
This should take in the even inputs and give the right outputs!

Find index of less or equal value in list recursively (python)

Got task to find indexes of value and double that value in input list.
In input first line we get list range, second - list of values, third - value to find.
The output is 2 numbers - indexes of equal or higher value and double the value. If there is none, return -1
Example input:
6
1 2 4 4 6 8
3
Example output:
3 5
What i got so far is standart binary search func, but i dont get how to make it search not only for exact number but nearest higher.
def binarySearch(arr, x, left, right):
if right <= left:
return -1
mid = (left + right) // 2
if arr[mid] >= x:
return mid
elif x < arr[mid]:
return binarySearch(arr, x, left, mid)
else:
return binarySearch(arr, x, mid + 1, right)
def main():
n = int(input())
k = input().split()
q = []
for i in k:
q.append(int(i))
s = int(input())
res1 = binarySearch(q, s, q[0], (n-1))
res2 = binarySearch(q, (s*2), q[0], (n-1))
print(res1, res2)
if __name__ == "__main__":
main()
The input is:
6
1 2 4 4 6 8
3
And output:
3 4
Here's a modified binary search which will return the base zero index of a value if found or the index of the next highest value in the list.
def bsearch(lst, x):
L = 0
R = len(lst) - 1
while L <= R:
m = (L + R) // 2
if (v := lst[m]) == x:
return m
if v < x:
L = m + 1
else:
R = m - 1
return L if L < len(lst) else -1
data = list(map(int, '1 2 4 4 6 8'.split()))
for x in range(10):
print(x, bsearch(data, x))
Output:
0 0
1 0
2 1
3 2
4 2
5 4
6 4
7 5
8 5
9 -1

Python - Print steps of an extended euclidean algorithm

Here is the current extended euclidean algorithm I found online :
def euclideEtendu(bNombre, aModulo):
""" Algorithme d'Euclide étendu, permettant de connaître:
PGCD
Coefficients de Bézout (u, v)
Inverse modulaire de B modulo A ---> B * B^-1 mod A = 1
"""
modulo = aModulo
x = 0
y = 1
u = 1
v = 0
while bNombre != 0:
q = aModulo // bNombre
r = aModulo % bNombre
m = x - u * q
n = y - v * q
aModulo = bNombre
bNombre = r
x = u
y = v
u = m
v = n
' retourne (pgcd, u, v, inverse modulaire '
return (aModulo, x, y, x % modulo)
Here is an example :
>>> euclideEtendu(17, 13)
(1, -3, 4, 10)
And here is what I want it to return :
>>> euclideEtendu(17, 13)
1 = 13 - 3 * 4
1 = 13 - 3 * (17 - 1 * 13)
1 = 4 * 13 - 3 * 17
17x + 13y = 1
17 * -3 + 13 * 4 = 1
So adding all the "steps".
Thanks in advance.

Compare and count same digits between two numbers

I'm looking to write a function that receives two four-digit numbers (m, n) that counts how many digits are the same between m and n, including duplicates and zeroes on the left. The thing is, my professor only taught us how to use loops, and don't want us to use lists and intersections, and I'm no able to do it.
For example, if m = 331 and n = 3, it should return 2 as the amount of equal digits, bit if n = 33, it should return 3 same digits.
>>> compare_digits(331, 3)
2
>>> compare_digits(332, 33)
3
Edit: This is the code I created before, and it counts same digits more than it should, but the central idea is the usage of % and // to read each digit, but it's not working...
def compare_digits(m, n):
read_ndigits = 0
same_digits = 0
while read_ndigits < 4: #number of digits
current_n = n % 10
read_mdigits = 0
while read_mdigits < 4:
current_m = m % 10
if current_n == current_m:
same_digits += 1
m //= 10
read_mdigits += 1
n //= 10
read_ndigits += 1
return same_digits
The output is very messy and I can't even recognize any pattern.
You can use collections.Counter() with set intersection:
from collections import Counter
def compare_digits(m, n):
m_counts = Counter(str(m).zfill(4))
n_counts = Counter(str(n).zfill(4))
return sum(min(m_counts[k], n_counts[k]) for k in m_counts.keys() & n_counts.keys())
print(compare_digits(331, 3)) # 2
print(compare_digits(332, 33)) # 3
print(compare_digits(3, 331)) # 2
Well, I decided to limit the number of digits to 4 and not be generic about it, so I wrote this and it worked perfectly:
def compare_digits(m, n):
a = m % 10
m //= 10
b = m % 10
m //= 10
c = m % 10
m //= 10
d = m % 10
read_ndigits = 0
same_digits = 0
while read_ndigits < 4:
current = n % 10
if current == a:
same_digits += 1
a = None
elif current == b:
same_digits += 1
b = None
elif current == c:
same_digits += 1
c = None
elif current == d:
same_digits += 1
d = None
n //= 10
read_ndigits += 1
return same_digits
Thank you all for your help :)

Categories