2
0
Fork 0
mirror of https://github.com/MartinThoma/LaTeX-examples.git synced 2025-04-26 06:48:04 +02:00
LaTeX-examples/source-code/Pseudocode/SolveLinearCongruences/solveLinearCongruences.py

54 lines
1.2 KiB
Python
Raw Normal View History

2013-09-01 17:40:24 +02:00
#!/usr/bin/env python
# -*- coding: utf-8 -*-
2015-11-20 23:12:22 +01:00
def extended_euclidean_algorithm(a, b):
"""
Calculates gcd(a,b) and a linear combination such that
gcd(a,b) = a*x + b*y
As a side effect:
If gcd(a,b) = 1 = a*x + b*y
Then x is multiplicative inverse of a modulo b.
"""
aO, bO = a, b
x = lasty = 0
y = lastx = 1
while (b != 0):
q = a/b
a, b = b, a % b
x, lastx = lastx-q*x, x
y, lasty = lasty-q*y, y
return {
"x": lastx,
"y": lasty,
"gcd": aO * lastx + bO * lasty
}
def solve_linear_congruence_equations(rests, modulos):
"""
Solve a system of linear congruences.
Examples
--------
>>> solve_linear_congruence_equations([4, 12, 14], [19, 37, 43])
{'congruence class': 22804, 'modulo': 30229}
"""
assert len(rests) == len(modulos)
x = 0
M = reduce(lambda x, y: x*y, modulos)
for mi, resti in zip(modulos, rests):
Mi = M / mi
s = extended_euclidean_algorithm(Mi, mi)["x"]
e = s * Mi
x += resti * e
return {"congruence class": ((x % M) + M) % M, "modulo": M}
2013-09-01 17:40:24 +02:00
if __name__ == "__main__":
2015-11-20 23:12:22 +01:00
import doctest
doctest.testmod()