for the problem Ax ≡ B (MOD C) I did this, and it was okay:
def congru(a,b,c):
for i in range(0,c):
if ((a*i - b)%c)== 0 :
print(i)
Now I have to solve a system of equations, where A = ( 5x + 7y) and A= (6x + 2y),
and B= 4 and B = 12 , respectively, and C is 26.
In other words:
( 5x + 7y)≡ 4 (mod 26)
(6x + 2y)≡ 12 (mod 26)
How do I do that?
Thanks.
For the aX ≡ b (mod m) linear congruence, here is a more powerful Python solution, based on Euler's theorem, which will work well even for very large numbers:
def linear_congruence(a, b, m):
if b == 0:
return 0
if a < 0:
a = -a
b = -b
b %= m
while a > m:
a -= m
return (m * linear_congruence(m, -b, a) + b) // a
>>> linear_congruence(80484954784936, 69992716484293, 119315717514047)
>>> 45347150615590
For the X, Y system: multiply 1st equation by 2 and the 2nd one by -7, add them together and solve for X. Then substitute X and solve for Y.
This is a very fast linear congruence solver that can solve a 4096 byte number in a second. Recursion versions meet their max depth at this length:
#included if you use withstats=True, not needed otherwise
def ltrailing(N):
return len(str(bin(N))) - len(str(bin(N)).rstrip('0'))
#included if you use withstats=True, not needed otherwise
def _testx(n, b, withstats=False):
s = ltrailing(n - 1)
t = n >> s
if b == 1 or b == n - 1:
return True
else:
for j in range(0, s):
b = pow_mod(b, 2, n, withstats)
if b == n - 1:
return True
if b == 1:
return False
if withstats == True:
print(f"{n}, {b}, {s}, {t}, {j}")
if withstats == True:
print(f"{n}, {b}, {s}, {t}")
return False
def fastlinearcongruence(powx, divmodx, N, withstats=False):
x, y, z = egcditer(powx, N, withstats)
answer = (y*divmodx)%N
if withstats == True:
print(f"answer = {answer}, mrbt = {a}, mrst = {b}, mranswer = {_testx(N, answer)}")
if x > 1:
powx//=x
divmodx//=x
N//=x
if withstats == True:
print(f"powx = {powx}, divmodx = {divmodx}, N = {N}")
x, y, z = egcditer(powx, N, withstats)
if withstats == True:
print(f"x = {x}, y = {y}, z = {z}")
answer = (y*divmodx)%N
if withstats == True:
print(f"answer = {answer}, mrbt = {a}, mrst = {b}, mranswer = {_testx(N, answer)}")
answer = (y*divmodx)%N
if withstats == True:
print(f"answer = {answer}, mrbt = {a}, mrst = {b}, mranswer = {_testx(N, answer)}")
return answer
def egcditer(a, b, withstats=False):
s = 0
r = b
old_s = 1
old_r = a
quotient = 0
if withstats == True:
print(f"quotient = {quotient}, old_r = {old_r}, r = {r}, old_s = {old_s}, s = {s}")
while r!= 0:
quotient = old_r // r
old_r, r = r, old_r - quotient * r
old_s, s = s, old_s - quotient * s
if withstats == True:
print(f"quotient = {quotient}, old_r = {old_r}, r = {r}, old_s = {old_s}, s = {s}")
if b != 0:
bezout_t = quotient = (old_r - old_s * a) // b
if withstats == True:
print(f"bezout_t = {bezout_t}")
else:
bezout_t = 0
if withstats == True:
print("Bézout coefficients:", (old_s, bezout_t))
print("greatest common divisor:", old_r)
return old_r, old_s, bezout_t
To use:
In [2703]: fastlinearcongruence(63,1,1009)
Out[2703]: 993
In [2705]: fastlinearcongruence(993,1,1009)
Out[2705]: 63
Also this is 100x faster than pow when performing this pow:
pow(1009, 2**bit_length()-1, 2**bit_length())
where the answer is 273.
This is equivalent to the much faster:
In [2713]: fastlinearcongruence(1009,1,1024)
Out[2713]: 273
Solved, here's the code for it:
def congru(a0,a1,a2,b0,b1,b2,c):
for i in range(0,c):
for j in range(0,c):
if ((a0*i + a1*j) - a2)%c ==0 and ((b0*i +b1*j)-b2)%c==0:
print('x: %d y: %d' %( i, j))
If you need a congruence system you can use this code.
from functools import reduce
class CI:
"""
cX=a (mod m)
"""
def __init__(self, c, a, m):
self.c = c%m
self.a = a%m
self.m = m
def solve(self, x):
return (x*self.c)%self.m == self.a
def find(cil):
espacio = reduce(lambda acc, ci: acc*ci.m, cil, 1)+1
for x in range(0, espacio):
if reduce(lambda acc, ci: acc and ci.solve(x), cil, True):
return x
print(find([CI(3, 2, 4), CI(4, 1, 5), CI(6, 3, 9)]))
this example will solve for x
3x=2 (mod 2)
4x=1 (mod 1)
6x=3 (mod 9)
To solve linear congruence system, You should use Chinese theorem of reminders.
I wrote full code using python and AppJar (AppJar is for grafics).
And You can download it from my github profile: github profile, full code there
There You can find all the functions I used.
It is very simple and I am sure You will understand the code, although it is written in serbian language.
Related
just a small labyrinth solver. try it to on python but dont even understand why it doesnt print anything. Im just started with python and trying to actually translate my teachers code from cpp just for interest.
need to reach to the destination after visiting each cell
m = [
[2,0,0,0,0,0],
[0,0,0,0,0,0],
[0,0,0,0,0,0],
[0,0,0,0,0,0],
[0,0,0,2,0,0],
[0,0,0,0,0,0]
]
STOP = 34
r = 0
c = 0
def init( r_: int = 0, c_: int = 0) -> None:
r = 0
c = 0
def step(r,c,level):
if level==STOP-1:
if r == 3 and c == 5:
for i in range(0,level):
print("("+init(int(r),int(c))+"," + init(int(r),int(c)) + ") - ")
print("(3,5)\n")
return True
else:
return False
m[r][c]=1
if c > 0 and m[r][c - 1] == 0:
if step(r, c - 1, level + 1):
return True
if c < 5 and m[r][c + 1] == 0:
if (step(r, c + 1, level + 1)):
return True
if r > 0 and m[r - 1][c] == 0:
if (step(r - 1, c, level + 1)):
return True
if r < 5 and m[r + 1][c] == 0:
if (step(r + 1, c, level + 1)):
return True
m[r][c] = 0
return False
def main(argc, argv):
step(0, 1, 0)
Python doesn't automatically call main like c does, nor does it require a main function. Your code can just live in the top level (e.g. print('hello world') is a valid, complete program)
Change this line:
def main(argc, argv):
to this:
if __name__ == '__main__':
got it
import matplotlib.pyplot as plt
S, F, W, X = 1, 2, 0, None
FIELD = [[X,S,W,W,W,W],
[W,W,W,W,W,W],
[W,W,W,W,W,W],
[W,W,W,W,W,F],
[W,W,W,X,W,W],
[W,W,W,W,W,W]]
ROWS = len(FIELD)
COLS = len(FIELD[0])
START_POS = [(i, line.index(S)) for i, line in enumerate(FIELD) if S in line][0]
FINISH_POS = [(i, line.index(F)) for i, line in enumerate(FIELD) if F in line][0]
STEPS = sum(line.count(W) for line in FIELD) + 1
print("Start:", START_POS, "\nFinish:", FINISH_POS, "\nTotal steps:", STEPS)
def do_step(level, path, points):
global FIELD
r, c = points[-1]
if r<0 or c<0 or r>=ROWS or c>=COLS or FIELD[r][c] == X:
return
if level == STEPS and (r, c) == FINISH_POS:
print("Found path:", path)
yy, xx = zip(*points)
plt.plot(xx, yy, "-ok")
plt.gca().invert_yaxis()
plt.show()
exit()
current = FIELD[r][c]
FIELD[r][c] = X
for dr, dc, dir in ((-1,0,'^'), (0,1,'>'), (1,0,'v'), (0,-1,'<')):
do_step(level+1, path+dir, points+[(r+dr,c+dc)])
FIELD[r][c] = current
do_step(0, "", [START_POS])
print("No path's found.")
I wrote the Extended Euclidean Algorithm, but i'm having trouble with using it to solve the following equation:
which the Modular Equation Solver reduces to
and
Here is my code:
def fastlinearcongruenceSO(powx, divmodx, N, withstats=False):
x, y, z = egcditerx2SO(powx, N, withstats)
answer = (y*divmodx)%N
if withstats == True:
print(f"answer = {answer}")
if x > 1:
powx//=x
divmodx//=x
N//=x
if withstats == True:
print(f"powx = {powx}, divmodx = {divmodx}, N = {N}")
x, y, z = egcditerx2SO(powx, N, withstats)
if withstats == True:
print(f"x = {x}, y = {y}, z = {z}")
answer = (y*divmodx)%N
if withstats == True:
print(f"answer = {answer}")
return answer
def egcditerx2SO(a, b, withstats=False):
s = 0
r = b
old_s = 1
old_r = a
quotient = 0
if withstats == True:
print(f"quotient = {quotient}, old_r = {old_r}, r = {r}, old_s = {old_s}, s = {s}")
while r!= 0:
quotient = old_r // r
old_r, r = r, old_r - quotient * r
old_s, s = s, old_s - quotient * s
if withstats == True:
print(f"quotient = {quotient}, old_r = {old_r}, r = {r}, old_s = {old_s}, s = {s}")
if b != 0:
bezout_t = quotient = (old_r - old_s * a) // b
if withstats == True:
print(f"bezout_t = {bezout_t}")
else:
bezout_t = 0
if withstats == True:
print("Bézout coefficients:", (old_s, bezout_t))
print("greatest common divisor:", old_r)
return old_r, old_s, bezout_t
To solve for inverses, i used this form:
IN: fastlinearcongruenceSO(327, 1, 1009)
OUT: 108
I'm not sure how or what changes i need to make to modify it to solve with the form of division, does anyone have any ideas of what changes i need to make or if i can solve it using my existing code? I really want to modify my code to handle it solving this equation: 743360/1008x = 272 (mod 1009) and x == 116 or for someone to let me know how that equation was solved, and i can then with those steps modify my code to solve for division based modulus equations. Thanks for anyone who knows how to solve these division based equations.
here's the code i made
def bisection(f, a, b, e):
step = 1
condition = True
while condition:
c = (a+b)/2
if f(a) * f(c) < 0:
b = c
else:
a = c
if f(c) == 0:
break
step = step + 1
condition = abs(f(a)-f(b)) > e
print(c)
return(c)
if f(a)* f(b) > 0:
print("no roots")
else:
bisection(f, a, b, e)
a, b, e = input().split(' ')
a = float(a)
b = float(b)
print(round(root, 4))
but I'm getting a root of c = 0.171875
instead of 0.6875
I am creating a basic RSA encryption program without using an RSA library that takes a secret message, converts each character in the string to its ASCII value, encrypts with a public key and concatenates the values, and then decrypts it using a private key and returns it to a string.
All with the principle of cipher = pow(plain,e,n) and plain = pow(cipher,d,n). My issue is that when the numbers get very large as I need d and n to be 16 digits minimum, the pow() function seems to result in an error in calculation that yields an ASCII value that is out of range to convert to a character. I've been struggling to figure out where I'm going wrong for days now. Any help is appreciated. Code below:
from random import randrange, getrandbits
def is_prime(n, k=128):
# Test if n is not even.
# But care, 2 is prime !
if n == 2 or n == 3:
return True
if n <= 1 or n % 2 == 0:
return False
# find r and s
s = 0
r = n - 1
while r & 1 == 0:
s += 1
r //= 2
# do k tests
for q in range(k):
a = randrange(2, n - 1)
x = pow(a, r, n)
if x != 1 and x != n - 1:
j = 1
while j < s and x != n - 1:
x = pow(x, 2, n)
if x == 1:
return False
j += 1
if x != n - 1:
return False
return True
def generate_prime_candidate(length):
# generate random bits
p = getrandbits(length)
#p = randrange(10**7,9*(10**7))
# apply a mask to set MSB and LSB to 1
p |= (1 << length - 1) | 1
return p
def generate_prime_number(length=64):
p = 4
# keep generating while the primality test fail
while not is_prime(p, 128):
p = generate_prime_candidate(length)
return p
def gcd(a, b):
while b != 0:
a, b = b, a % b
return a
def generate_keypair(p, q):
n = p * q
#Phi is the totient of n
phi = (p-1) * (q-1)
#Choose an integer e such that e and phi(n) are coprime
e = randrange(1,65537)
g = gcd(e, phi)
while g != 1:
e = randrange(1,65537)
g = gcd(e, phi)
d = multiplicative_inverse(e, phi)
return ((e, n), (d, n))
def multiplicative_inverse(e, phi):
d = 0
k = 1
while True:
d = (1+(k*phi))/e
if((round(d,5)%1) == 0):
return int(d)
else:
k+=1
def encrypt(m,public):
key, n = public
encrypted = ''
print("Your original message is: ", m)
result = [(ord(m[i])) for i in range(0,len(m))]
encryption = [pow(result[i],key,n) for i in range(0,len(result))]
for i in range(0,len(encryption)):
encrypted = encrypted + str(encryption[i])
#encrypted = pow(int(encrypted),key,n)
print("Your encrypted message is: ", encrypted)
#return result,encrypted
return encrypted, encryption
def decrypt(e,c,private):
key, n = private
print("Your encrypted message is: ", c)
print(e)
decryption = [pow(e[i],key,n) for i in range(0,len(e))]
print(decryption)
result = [chr(decryption[i])for i in range(0,len(decryption)) ]
decrypted = ''.join(result)
print("Your decrypted message is: ",decrypted)
return result,decrypted
def fastpow(x,y,p):
res = 1
x = x%p
while(y>0):
if((y&1) == 1):
res = (res*x)%p
y = y>>1
x = (x*x)%p
return res
message = input("Enter your secret message: ")
p1 = generate_prime_number()
p2 = generate_prime_number()
public, private = generate_keypair(p1,p2)
print("Your public key is ", public)
print("Your private key is ", private)
encrypted,cipher = encrypt(message,public)
decrypt(cipher,encrypted,private)
Traceback:
File "<ipython-input-281-bce7c44b930c>", line 1, in <module>
runfile('C:/Users/Mervin/Downloads/group2.py', wdir='C:/Users/Mervin/Downloads')
File "C:\Users\Mervin\Anaconda3\lib\site-packages\spyder\util\site\sitecustomize.py", line 705, in runfile
execfile(filename, namespace)
File "C:\Users\Mervin\Anaconda3\lib\site-packages\spyder\util\site\sitecustomize.py", line 102, in execfile
exec(compile(f.read(), filename, 'exec'), namespace)
File "C:/Users/Mervin/Downloads/group2.py", line 125, in <module>
decrypt(cipher,encrypted,private)
File "C:/Users/Mervin/Downloads/group2.py", line 100, in decrypt
result = [chr(decryption[i])for i in range(0,len(decryption)) ]
File "C:/Users/Mervin/Downloads/group2.py", line 100, in <listcomp>
result = [chr(decryption[i])for i in range(0,len(decryption)) ]
OverflowError: Python int too large to convert to C long
Your method multiplicative_inverse is not correct. I'm not certain what you are doing in that method with the round method and floating point division, but even if you got that part correct it would be too slow anyway, requiring O(φ) steps. The usual method for computing modular multiplicative inverses is an adaptation of the extended Euclidean algorithm, which runs in O(log(φ)2) steps. Here is a straightforward mapping from the psuedocode in the Wikipedia article to python 3 code:
def multiplicative_inverse(a, n):
t, newt = 0, 1
r, newr = n, a
while newr:
quotient = r // newr
t, newt = newt, t - quotient * newt
r, newr = newr, r - quotient * newr
if r > 1:
raise ZeroDivisionError("{} is not invertible".format(a))
if t < 0:
t = t + n
return t
I tried making this code and run it, but the result showed "None".
I've edited by adding another else in the loop function, then it actually produces a int result of '57' which is not exactly the answer.
def double(n):
return n*2
def halve(n):
return n//2
def mult(m,n):
def loop(m,n):
if n>1:
if n%2 != 0:
return m + loop(double(m),halve(n))
else:
return m #added another else
else:
return m
if n>0:
return loop(m,n)
else:
return 0
print(mult(57,86))
by simple recursion
def double(n):
return n * 2
def halve(n):
return n // 2
def mult(m, n, a = 0):
if n % 2 != 0:
a = a + m
m = double(m)
n = halve(n)
if n % 2 == 0:
m = double(m)
n = halve(n)
if n != 0:
return mult(m, n, a)
return a
print(mult(57, 86))
by nested function
def double(n):
return n * 2
def halve(n):
return n // 2
def mult(m, n):
def loop(m, n, a = 0):
if n % 2 != 0:
a = a + m
m = double(m)
n = halve(n)
if n % 2 == 0:
m = double(m)
n = halve(n)
if n != 0:
return loop(m, n, a)
return a
return loop(m, n)
print(mult(57, 86))