From f810adf89019c52460e5fac6043ffdd0f4488a56 Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Tue, 13 Aug 2019 02:05:59 +0200 Subject: [PATCH 01/11] Update .gitignore to remove __pycache__/ --- .gitignore | 34 +++++++++++++++++++++++++--------- 1 file changed, 25 insertions(+), 9 deletions(-) diff --git a/.gitignore b/.gitignore index 0c3f33058614..b840d4ed0490 100644 --- a/.gitignore +++ b/.gitignore @@ -7,9 +7,7 @@ __pycache__/ *.so # Distribution / packaging -.vscode/ .Python -env/ build/ develop-eggs/ dist/ @@ -21,9 +19,11 @@ lib64/ parts/ sdist/ var/ +wheels/ *.egg-info/ .installed.cfg *.egg +MANIFEST # PyInstaller # Usually these files are written by a python script from a template @@ -43,8 +43,9 @@ htmlcov/ .cache nosetests.xml coverage.xml -*,cover +*.cover .hypothesis/ +.pytest_cache/ # Translations *.mo @@ -53,6 +54,7 @@ coverage.xml # Django stuff: *.log local_settings.py +db.sqlite3 # Flask stuff: instance/ @@ -67,7 +69,7 @@ docs/_build/ # PyBuilder target/ -# IPython Notebook +# Jupyter Notebook .ipynb_checkpoints # pyenv @@ -76,18 +78,32 @@ target/ # celery beat schedule file celerybeat-schedule -# dotenv -.env +# SageMath parsed files +*.sage.py -# virtualenv +# Environments +.env +.venv +env/ venv/ ENV/ +env.bak/ +venv.bak/ # Spyder project settings .spyderproject +.spyproject # Rope project settings .ropeproject -.idea + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ + .DS_Store -.try \ No newline at end of file +.idea +.try +.vscode/ From 2b7a31e69e5529e24e44d42147ebd525bb0d0666 Mon Sep 17 00:00:00 2001 From: OddExtension5 Date: Tue, 1 Oct 2019 21:26:51 +0530 Subject: [PATCH 02/11] added chinese_remainder_theorem --- .../chinese_remainder_theorem.py | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 data_structures/hashing/number_theory/chinese_remainder_theorem.py diff --git a/data_structures/hashing/number_theory/chinese_remainder_theorem.py b/data_structures/hashing/number_theory/chinese_remainder_theorem.py new file mode 100644 index 000000000000..a61ed16e41b2 --- /dev/null +++ b/data_structures/hashing/number_theory/chinese_remainder_theorem.py @@ -0,0 +1,44 @@ +# Chinese Remainder Theorem: + +# If GCD(a,b) = 1, then for any remainder ra modulo a and any remainder rb modulo b there exists integer n, +# such that n = ra (mod a) and n = ra(mod b). If n1 and n2 are two such integers, then n1=n2(mod ab) + +# Algorithm : + +# 1. Use extended euclid algorithm to find x,y such that a*x + b*y = 1 +# 2. Take n = ra*by + rb*ax + + +# Extended Euclid +def ExtendedEuclid(a, b): + if b == 0: + return (1, 0) + (x, y) = ExtendedEuclid(b, a % b) + k = a // b + return (y, x - k * y) + + +# Uses ExtendedEuclid to find inverses +def ChineseRemainderTheorem(n1, r1, n2, r2): + (x, y) = ExtendedEuclid(n1, n2) + m = n1 * n2 + n = r2 * x * n1 + r1 * y * n2 + return ((n % m + m) % m) + + +# ----------SAME SOLUTION USING InvertModulo instead ExtendedEuclid---------------- + +# This function find the inverses of a i.e., a^(-1) +def InvertModulo(a, n): + (b, x) = ExtendedEuclid(a, n) + if b < 0: + b = (b % n + n) % n + return b + + +# Same a above using InvertingModulo +def ChineseRemainderTheorem2(n1, r1, n2, r2): + x, y = InvertModulo(n1, n2), InvertModulo(n2, n1) + m = n1 * n2 + n = r2 * x * n1 + r1 * y * n2 + return (n % m + m) % m From 41a9414dec38b622f12fb572957accc6265a0212 Mon Sep 17 00:00:00 2001 From: OddExtension5 Date: Tue, 1 Oct 2019 22:09:59 +0530 Subject: [PATCH 03/11] Added Diophantine_equation algorithm --- .../number_theory/diophantine_equation.py | 64 +++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 data_structures/hashing/number_theory/diophantine_equation.py diff --git a/data_structures/hashing/number_theory/diophantine_equation.py b/data_structures/hashing/number_theory/diophantine_equation.py new file mode 100644 index 000000000000..47040ee6a932 --- /dev/null +++ b/data_structures/hashing/number_theory/diophantine_equation.py @@ -0,0 +1,64 @@ +# Diophantine Equation : Given integers a,b,c ( at least one of a and b != 0), the diophantine equation +# a*x + b*y = c has a solution (where x and y are integers) iff gcd(a,b) divides c. + + +def diophantine(a, b, c): + assert c % gcd(a, b) == 0 # gcd(a,b) function implemented below + + (d, x, y) = extended_gcd(a, b) # extended_gcd(a,b) function implemented below + r = c / d + return (r * x, r * y) + + +# Lemma : if n|ab and gcd(a,n) = 1, then n|b. + +# Finding All solutions of Diophantine Equations: + +# Theorem : Let gcd(a,b) = d, a = d*p, b = d*q. If (x0,y0) is a solution of Diophantine Equation a*x + b*y = c. +# a*x0 + b*y0 = c, then all the solutions have the form a(x0 + t*q) + b(y0 - t*p) = c, where t is an arbitrary integer. + +# n is the number of solution you want, n = 2 by default + +def diophantine_all_soln(a, b, c, n=2): + (x0, y0) = diophantine(a, b, c) + d = gcd(a, b) + p = a // d + q = b // d + + for i in range(n): + x = x0 + i * q + y = y0 - i * p + print(x, y) + + +# Euclid's Lemma : d divides a and b, if and only if d divides a-b and b + +# Euclid's Algorithm + +def gcd(a, b): + if a < b: + a, b = b, a + + while a % b != 0: + a, b = b, a % b + + return b + + +# Extended Euclid's Algorithm : If d divides a and b and d = a*x + b*y for integers x and y, then d = gcd(a,b) + + +def extended_gcd(a, b): + assert a >= 0 and b >= 0 + + if b == 0: + d, x, y = a, 1, 0 + else: + (d, p, q) = extended_gcd(b, a % b) + x = q + y = p - q * (a // b) + + assert a % d == 0 and b % d == 0 + assert d == a * x + b * y + + return (d, x, y) From 72e9db49a52525227290698a4200d29dfd7f52b7 Mon Sep 17 00:00:00 2001 From: OddExtension5 Date: Wed, 2 Oct 2019 00:07:22 +0530 Subject: [PATCH 04/11] Update Diophantine eqn & chinese remainder theorem --- .../chinese_remainder_theorem.py | 26 +++++++++++++ .../number_theory/diophantine_equation.py | 38 +++++++++++++++++++ 2 files changed, 64 insertions(+) diff --git a/data_structures/hashing/number_theory/chinese_remainder_theorem.py b/data_structures/hashing/number_theory/chinese_remainder_theorem.py index a61ed16e41b2..ed519d56b68e 100644 --- a/data_structures/hashing/number_theory/chinese_remainder_theorem.py +++ b/data_structures/hashing/number_theory/chinese_remainder_theorem.py @@ -8,6 +8,9 @@ # 1. Use extended euclid algorithm to find x,y such that a*x + b*y = 1 # 2. Take n = ra*by + rb*ax +# import testmod for testing our function +from doctest import testmod + # Extended Euclid def ExtendedEuclid(a, b): @@ -20,6 +23,17 @@ def ExtendedEuclid(a, b): # Uses ExtendedEuclid to find inverses def ChineseRemainderTheorem(n1, r1, n2, r2): + """ + >>> ChineseRemainderTheorem(5,1,7,3) + 31 + + Explanation : 31 is the smallest number such that + (i) When we divide it by 5, we get remainder 1 + (ii) When we divide it by 7, we get remainder 3 + + >>> ChineseRemainderTheorem(6,1,4,3) + 14 + """ (x, y) = ExtendedEuclid(n1, n2) m = n1 * n2 n = r2 * x * n1 + r1 * y * n2 @@ -38,7 +52,19 @@ def InvertModulo(a, n): # Same a above using InvertingModulo def ChineseRemainderTheorem2(n1, r1, n2, r2): + """ + >>> ChineseRemainderTheorem2(5,1,7,3) + 31 + + >>> ChineseRemainderTheorem2(6,1,4,3) + 14 + """ x, y = InvertModulo(n1, n2), InvertModulo(n2, n1) m = n1 * n2 n = r2 * x * n1 + r1 * y * n2 return (n % m + m) % m + + +if __name__ == '__main__': + testmod(name='ChineseRemainderTheorem', verbose=True) + testmod(name='ChineseRemainderTheorem2', verbose=True) diff --git a/data_structures/hashing/number_theory/diophantine_equation.py b/data_structures/hashing/number_theory/diophantine_equation.py index 47040ee6a932..435bb0438fdb 100644 --- a/data_structures/hashing/number_theory/diophantine_equation.py +++ b/data_structures/hashing/number_theory/diophantine_equation.py @@ -1,8 +1,23 @@ # Diophantine Equation : Given integers a,b,c ( at least one of a and b != 0), the diophantine equation # a*x + b*y = c has a solution (where x and y are integers) iff gcd(a,b) divides c. +# import testmod for testing our function +from doctest import testmod + def diophantine(a, b, c): + """ + >>> diophantine(10,6,14) + (-7.0, 14.0) + + >>> diophantine(391,299,-69) + (9.0, -12.0) + + But above equation has one more solution i.e., x = -4, y = 5. + That's why we need diophantine all solution function. + + """ + assert c % gcd(a, b) == 0 # gcd(a,b) function implemented below (d, x, y) = extended_gcd(a, b) # extended_gcd(a,b) function implemented below @@ -20,6 +35,24 @@ def diophantine(a, b, c): # n is the number of solution you want, n = 2 by default def diophantine_all_soln(a, b, c, n=2): + """ + >>> diophantine_all_soln(10, 6, 14) + -7.0 14.0 + -4.0 9.0 + + >>> diophantine_all_soln(10, 6, 14, 4) + -7.0 14.0 + -4.0 9.0 + -1.0 4.0 + 2.0 -1.0 + + >>> diophantine_all_soln(391, 299, -69, n = 4) + 9.0 -12.0 + 22.0 -29.0 + 35.0 -46.0 + 48.0 -63.0 + + """ (x0, y0) = diophantine(a, b, c) d = gcd(a, b) p = a // d @@ -62,3 +95,8 @@ def extended_gcd(a, b): assert d == a * x + b * y return (d, x, y) + + +if __name__ == '__main__': + testmod(name='diophantine', verbose=True) + testmod(name='diophantine_all_soln', verbose=True) From 33de1b1af0b8ded4032e1fb166fffb9427085fe7 Mon Sep 17 00:00:00 2001 From: OddExtension5 Date: Wed, 2 Oct 2019 11:08:12 +0530 Subject: [PATCH 05/11] Update Diophantine eqn & chinese remainder theorem --- .../chinese_remainder_theorem.py | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/data_structures/hashing/number_theory/chinese_remainder_theorem.py b/data_structures/hashing/number_theory/chinese_remainder_theorem.py index ed519d56b68e..c552241c139b 100644 --- a/data_structures/hashing/number_theory/chinese_remainder_theorem.py +++ b/data_structures/hashing/number_theory/chinese_remainder_theorem.py @@ -13,28 +13,28 @@ # Extended Euclid -def ExtendedEuclid(a, b): +def extended_euclid(a, b): if b == 0: return (1, 0) - (x, y) = ExtendedEuclid(b, a % b) + (x, y) = extended_euclid(b, a % b) k = a // b return (y, x - k * y) # Uses ExtendedEuclid to find inverses -def ChineseRemainderTheorem(n1, r1, n2, r2): +def chinese_remainder_theorem(n1, r1, n2, r2): """ - >>> ChineseRemainderTheorem(5,1,7,3) + >>> chinese_remainder_theorem(5,1,7,3) 31 Explanation : 31 is the smallest number such that (i) When we divide it by 5, we get remainder 1 (ii) When we divide it by 7, we get remainder 3 - >>> ChineseRemainderTheorem(6,1,4,3) + >>> chinese_remainder_theorem(6,1,4,3) 14 """ - (x, y) = ExtendedEuclid(n1, n2) + (x, y) = extended_euclid(n1, n2) m = n1 * n2 n = r2 * x * n1 + r1 * y * n2 return ((n % m + m) % m) @@ -43,28 +43,28 @@ def ChineseRemainderTheorem(n1, r1, n2, r2): # ----------SAME SOLUTION USING InvertModulo instead ExtendedEuclid---------------- # This function find the inverses of a i.e., a^(-1) -def InvertModulo(a, n): - (b, x) = ExtendedEuclid(a, n) +def invert_modulo(a, n): + (b, x) = extended_euclid(a, n) if b < 0: b = (b % n + n) % n return b # Same a above using InvertingModulo -def ChineseRemainderTheorem2(n1, r1, n2, r2): +def chinese_remainder_theorem2(n1, r1, n2, r2): """ - >>> ChineseRemainderTheorem2(5,1,7,3) + >>> chinese_remainder_theorem2(5,1,7,3) 31 - >>> ChineseRemainderTheorem2(6,1,4,3) + >>> chinese_remainder_theorem2(6,1,4,3) 14 """ - x, y = InvertModulo(n1, n2), InvertModulo(n2, n1) + x, y = invert_modulo(n1, n2), invert_modulo(n2, n1) m = n1 * n2 n = r2 * x * n1 + r1 * y * n2 return (n % m + m) % m if __name__ == '__main__': - testmod(name='ChineseRemainderTheorem', verbose=True) - testmod(name='ChineseRemainderTheorem2', verbose=True) + testmod(name='chinese_remainder_theorem', verbose=True) + testmod(name='chinese_remainder_theorem2', verbose=True) From df00bf03937c3117bd24c2288fcdc05fb22eaffa Mon Sep 17 00:00:00 2001 From: OddExtension5 Date: Wed, 2 Oct 2019 12:04:10 +0530 Subject: [PATCH 06/11] added efficient modular division algorithm --- .../hashing/number_theory/modular_division.py | 94 +++++++++++++++++++ 1 file changed, 94 insertions(+) create mode 100644 data_structures/hashing/number_theory/modular_division.py diff --git a/data_structures/hashing/number_theory/modular_division.py b/data_structures/hashing/number_theory/modular_division.py new file mode 100644 index 000000000000..81853f3d9014 --- /dev/null +++ b/data_structures/hashing/number_theory/modular_division.py @@ -0,0 +1,94 @@ +# Modular Division +# An efficient algorithm for dividing b by a modulo n. + +# Given three integers a, b, and n, such that gcd(a,n)=1 and n>1, the algorithm should return an integer x such that +# 0≤x≤n−1, and b/a=x(modn) (that is, b=ax(modn)). + +# Theorem: +# a has a multiplicative inverse modulo n iff gcd(a,n) = 1 + + +# This find x = b*a^(-1) mod n +# Uses ExtendedEuclid to find the inverse of a + +# Import testmod for testing our function +from doctest import testmod + + +def modular_division(a, b, n): + """ + >>> modular_division(4,8,5) + 2 + + >>> modular_division(3,8,5) + 1 + + >>> modular_division(4, 11, 5) + 4 + + """ + assert n > 1 and a > 0 and gcd(a, n) == 1 + (d, t, s) = extended_gcd(n, a) # Implemented below + x = (b * s) % n + return x + + +# This function find the inverses of a i.e., a^(-1) +def invert_modulo(a, n): + (b, x) = extended_euclid(a, n) # Implemented below + if b < 0: + b = (b % n + n) % n + return b + + +# ------------------ Finding Modular division using invert_modulo ------------------- + +# This function used the above inversion of a to find x = (b*a^(-1))mod n +def modular_division2(a, b, n): + """ + >>> modular_division2(4,8,5) + 2 + + >>> modular_division2(3,8,5) + 1 + + >>> modular_division2(4, 11, 5) + 4 + + """ + s = invert_modulo(a, n) + x = (b * s) % n + return x + + +# Extended Euclid's Algorithm : If d divides a and b and d = a*x + b*y for integers x and y, then d = gcd(a,b) + + +def extended_gcd(a, b): + assert a >= 0 and b >= 0 + + if b == 0: + d, x, y = a, 1, 0 + else: + (d, p, q) = extended_gcd(b, a % b) + x = q + y = p - q * (a // b) + + assert a % d == 0 and b % d == 0 + assert d == a * x + b * y + + return (d, x, y) + + +# Extended Euclid +def extended_euclid(a, b): + if b == 0: + return (1, 0) + (x, y) = extended_euclid(b, a % b) + k = a // b + return (y, x - k * y) + + +if __name__ == '__main__': + testmod(name='modular_division', verbose=True) + testmod(name='modular_division2', verbose=True) From 2b5c6542c452f5c668162049adcb4a8d398b3578 Mon Sep 17 00:00:00 2001 From: OddExtension5 Date: Wed, 2 Oct 2019 12:12:43 +0530 Subject: [PATCH 07/11] added GCD function --- .../hashing/number_theory/modular_division.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/data_structures/hashing/number_theory/modular_division.py b/data_structures/hashing/number_theory/modular_division.py index 81853f3d9014..333a62c94125 100644 --- a/data_structures/hashing/number_theory/modular_division.py +++ b/data_structures/hashing/number_theory/modular_division.py @@ -88,6 +88,18 @@ def extended_euclid(a, b): k = a // b return (y, x - k * y) +# Euclid's Lemma : d divides a and b, if and only if d divides a-b and b +# Euclid's Algorithm + +def gcd(a, b): + if a < b: + a, b = b, a + + while a % b != 0: + a, b = b, a % b + + return b + if __name__ == '__main__': testmod(name='modular_division', verbose=True) From 2492b5242e90526db9647ec7d94f7ce685214669 Mon Sep 17 00:00:00 2001 From: OddExtension5 Date: Wed, 2 Oct 2019 19:38:06 +0530 Subject: [PATCH 08/11] update chinese_remainder_theorem | dipohantine eqn | modular_division --- .../chinese_remainder_theorem.py | 27 ++++++++- .../number_theory/diophantine_equation.py | 36 +++++++++--- .../hashing/number_theory/modular_division.py | 55 +++++++++++++++++-- 3 files changed, 102 insertions(+), 16 deletions(-) diff --git a/data_structures/hashing/number_theory/chinese_remainder_theorem.py b/data_structures/hashing/number_theory/chinese_remainder_theorem.py index c552241c139b..f1409530a70e 100644 --- a/data_structures/hashing/number_theory/chinese_remainder_theorem.py +++ b/data_structures/hashing/number_theory/chinese_remainder_theorem.py @@ -1,4 +1,5 @@ # Chinese Remainder Theorem: +# GCD ( Greatest Common Divisor ) or HCF ( Highest Common Factor ) # If GCD(a,b) = 1, then for any remainder ra modulo a and any remainder rb modulo b there exists integer n, # such that n = ra (mod a) and n = ra(mod b). If n1 and n2 are two such integers, then n1=n2(mod ab) @@ -8,12 +9,17 @@ # 1. Use extended euclid algorithm to find x,y such that a*x + b*y = 1 # 2. Take n = ra*by + rb*ax -# import testmod for testing our function -from doctest import testmod - # Extended Euclid def extended_euclid(a, b): + """ + >>> extended_euclid(10, 6) + (-1, 2) + + >>> extended_euclid(7, 5) + (-2, 3) + + """ if b == 0: return (1, 0) (x, y) = extended_euclid(b, a % b) @@ -33,6 +39,7 @@ def chinese_remainder_theorem(n1, r1, n2, r2): >>> chinese_remainder_theorem(6,1,4,3) 14 + """ (x, y) = extended_euclid(n1, n2) m = n1 * n2 @@ -44,6 +51,14 @@ def chinese_remainder_theorem(n1, r1, n2, r2): # This function find the inverses of a i.e., a^(-1) def invert_modulo(a, n): + """ + >>> invert_modulo(2, 5) + 3 + + >>> invert_modulo(8,7) + 1 + + """ (b, x) = extended_euclid(a, n) if b < 0: b = (b % n + n) % n @@ -58,6 +73,7 @@ def chinese_remainder_theorem2(n1, r1, n2, r2): >>> chinese_remainder_theorem2(6,1,4,3) 14 + """ x, y = invert_modulo(n1, n2), invert_modulo(n2, n1) m = n1 * n2 @@ -65,6 +81,11 @@ def chinese_remainder_theorem2(n1, r1, n2, r2): return (n % m + m) % m +# import testmod for testing our function +from doctest import testmod + if __name__ == '__main__': testmod(name='chinese_remainder_theorem', verbose=True) testmod(name='chinese_remainder_theorem2', verbose=True) + testmod(name='invert_modulo', verbose=True) + testmod(name='extended_euclid', verbose=True) diff --git a/data_structures/hashing/number_theory/diophantine_equation.py b/data_structures/hashing/number_theory/diophantine_equation.py index 435bb0438fdb..3ac7094eed6b 100644 --- a/data_structures/hashing/number_theory/diophantine_equation.py +++ b/data_structures/hashing/number_theory/diophantine_equation.py @@ -1,8 +1,7 @@ # Diophantine Equation : Given integers a,b,c ( at least one of a and b != 0), the diophantine equation # a*x + b*y = c has a solution (where x and y are integers) iff gcd(a,b) divides c. -# import testmod for testing our function -from doctest import testmod +# GCD ( Greatest Common Divisor ) or HCF ( Highest Common Factor ) def diophantine(a, b, c): @@ -18,8 +17,7 @@ def diophantine(a, b, c): """ - assert c % gcd(a, b) == 0 # gcd(a,b) function implemented below - + assert c % greatest_common_divisor(a, b) == 0 # greatest_common_divisor(a,b) function implemented below (d, x, y) = extended_gcd(a, b) # extended_gcd(a,b) function implemented below r = c / d return (r * x, r * y) @@ -53,8 +51,8 @@ def diophantine_all_soln(a, b, c, n=2): 48.0 -63.0 """ - (x0, y0) = diophantine(a, b, c) - d = gcd(a, b) + (x0, y0) = diophantine(a, b, c) # Initial value + d = greatest_common_divisor(a, b) p = a // d q = b // d @@ -68,7 +66,18 @@ def diophantine_all_soln(a, b, c, n=2): # Euclid's Algorithm -def gcd(a, b): +def greatest_common_divisor(a, b): + """ + >>> greatest_common_divisor(7,5) + 1 + + Note : In number theory, two integers a and b are said to be relatively prime, mutually prime, or co-prime + if the only positive integer (factor) that divides both of them is 1 i.e., gcd(a,b) = 1. + + >>> greatest_common_divisor(121, 11) + 11 + + """ if a < b: a, b = b, a @@ -82,6 +91,14 @@ def gcd(a, b): def extended_gcd(a, b): + """ + >>> extended_gcd(10, 6) + (2, -1, 2) + + >>> extended_gcd(7, 5) + (1, -2, 3) + + """ assert a >= 0 and b >= 0 if b == 0: @@ -97,6 +114,11 @@ def extended_gcd(a, b): return (d, x, y) +# import testmod for testing our function +from doctest import testmod + if __name__ == '__main__': testmod(name='diophantine', verbose=True) testmod(name='diophantine_all_soln', verbose=True) + testmod(name='extended_gcd', verbose=True) + testmod(name='greatest_common_divisor', verbose=True) diff --git a/data_structures/hashing/number_theory/modular_division.py b/data_structures/hashing/number_theory/modular_division.py index 333a62c94125..6943f5fa4a0a 100644 --- a/data_structures/hashing/number_theory/modular_division.py +++ b/data_structures/hashing/number_theory/modular_division.py @@ -1,6 +1,8 @@ -# Modular Division +# Modular Division : # An efficient algorithm for dividing b by a modulo n. +# GCD ( Greatest Common Divisor ) or HCF ( Highest Common Factor ) + # Given three integers a, b, and n, such that gcd(a,n)=1 and n>1, the algorithm should return an integer x such that # 0≤x≤n−1, and b/a=x(modn) (that is, b=ax(modn)). @@ -11,9 +13,6 @@ # This find x = b*a^(-1) mod n # Uses ExtendedEuclid to find the inverse of a -# Import testmod for testing our function -from doctest import testmod - def modular_division(a, b, n): """ @@ -35,6 +34,14 @@ def modular_division(a, b, n): # This function find the inverses of a i.e., a^(-1) def invert_modulo(a, n): + """ + >>> invert_modulo(2, 5) + 3 + + >>> invert_modulo(8,7) + 1 + + """ (b, x) = extended_euclid(a, n) # Implemented below if b < 0: b = (b % n + n) % n @@ -63,8 +70,17 @@ def modular_division2(a, b, n): # Extended Euclid's Algorithm : If d divides a and b and d = a*x + b*y for integers x and y, then d = gcd(a,b) - def extended_gcd(a, b): + """ + >>> extended_gcd(10, 6) + (2, -1, 2) + + >>> extended_gcd(7, 5) + (1, -2, 3) + + ** extended_gcd function is used when d = gcd(a,b) is required in output + + """ assert a >= 0 and b >= 0 if b == 0: @@ -82,16 +98,36 @@ def extended_gcd(a, b): # Extended Euclid def extended_euclid(a, b): + """ + >>> extended_euclid(10, 6) + (-1, 2) + + >>> extended_euclid(7, 5) + (-2, 3) + + """ if b == 0: return (1, 0) (x, y) = extended_euclid(b, a % b) k = a // b return (y, x - k * y) + # Euclid's Lemma : d divides a and b, if and only if d divides a-b and b # Euclid's Algorithm -def gcd(a, b): +def greatest_common_divisor(a, b): + """ + >>> greatest_common_divisor(7,5) + 1 + + Note : In number theory, two integers a and b are said to be relatively prime, mutually prime, or co-prime + if the only positive integer (factor) that divides both of them is 1 i.e., gcd(a,b) = 1. + + >>> greatest_common_divisor(121, 11) + 11 + + """ if a < b: a, b = b, a @@ -101,6 +137,13 @@ def gcd(a, b): return b +# Import testmod for testing our function +from doctest import testmod + if __name__ == '__main__': testmod(name='modular_division', verbose=True) testmod(name='modular_division2', verbose=True) + testmod(name='invert_modulo', verbose=True) + testmod(name='extended_gcd', verbose=True) + testmod(name='extended_euclid', verbose=True) + testmod(name='greatest_common_divisor', verbose=True) From 8037edb4855967bbaffe1203607c9db498fe643c Mon Sep 17 00:00:00 2001 From: OddExtension5 Date: Wed, 2 Oct 2019 19:47:17 +0530 Subject: [PATCH 09/11] update chinese_remainder_theorem | dipohantine eqn | modular_division --- data_structures/hashing/number_theory/modular_division.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_structures/hashing/number_theory/modular_division.py b/data_structures/hashing/number_theory/modular_division.py index 6943f5fa4a0a..4e1623fbe923 100644 --- a/data_structures/hashing/number_theory/modular_division.py +++ b/data_structures/hashing/number_theory/modular_division.py @@ -26,7 +26,7 @@ def modular_division(a, b, n): 4 """ - assert n > 1 and a > 0 and gcd(a, n) == 1 + assert n > 1 and a > 0 and greatest_common_divisor(a, n) == 1 (d, t, s) = extended_gcd(n, a) # Implemented below x = (b * s) % n return x From 67f4feed51c72f3059ccee21b9288c4d036da299 Mon Sep 17 00:00:00 2001 From: OddExtension5 Date: Thu, 3 Oct 2019 17:31:30 +0530 Subject: [PATCH 10/11] added a new directory named blockchain & a files from data_structures/hashing/number_theory --- .../chinese_remainder_theorem.py | 91 ----------- .../number_theory/diophantine_equation.py | 124 --------------- .../hashing/number_theory/modular_division.py | 149 ------------------ 3 files changed, 364 deletions(-) delete mode 100644 data_structures/hashing/number_theory/chinese_remainder_theorem.py delete mode 100644 data_structures/hashing/number_theory/diophantine_equation.py delete mode 100644 data_structures/hashing/number_theory/modular_division.py diff --git a/data_structures/hashing/number_theory/chinese_remainder_theorem.py b/data_structures/hashing/number_theory/chinese_remainder_theorem.py deleted file mode 100644 index f1409530a70e..000000000000 --- a/data_structures/hashing/number_theory/chinese_remainder_theorem.py +++ /dev/null @@ -1,91 +0,0 @@ -# Chinese Remainder Theorem: -# GCD ( Greatest Common Divisor ) or HCF ( Highest Common Factor ) - -# If GCD(a,b) = 1, then for any remainder ra modulo a and any remainder rb modulo b there exists integer n, -# such that n = ra (mod a) and n = ra(mod b). If n1 and n2 are two such integers, then n1=n2(mod ab) - -# Algorithm : - -# 1. Use extended euclid algorithm to find x,y such that a*x + b*y = 1 -# 2. Take n = ra*by + rb*ax - - -# Extended Euclid -def extended_euclid(a, b): - """ - >>> extended_euclid(10, 6) - (-1, 2) - - >>> extended_euclid(7, 5) - (-2, 3) - - """ - if b == 0: - return (1, 0) - (x, y) = extended_euclid(b, a % b) - k = a // b - return (y, x - k * y) - - -# Uses ExtendedEuclid to find inverses -def chinese_remainder_theorem(n1, r1, n2, r2): - """ - >>> chinese_remainder_theorem(5,1,7,3) - 31 - - Explanation : 31 is the smallest number such that - (i) When we divide it by 5, we get remainder 1 - (ii) When we divide it by 7, we get remainder 3 - - >>> chinese_remainder_theorem(6,1,4,3) - 14 - - """ - (x, y) = extended_euclid(n1, n2) - m = n1 * n2 - n = r2 * x * n1 + r1 * y * n2 - return ((n % m + m) % m) - - -# ----------SAME SOLUTION USING InvertModulo instead ExtendedEuclid---------------- - -# This function find the inverses of a i.e., a^(-1) -def invert_modulo(a, n): - """ - >>> invert_modulo(2, 5) - 3 - - >>> invert_modulo(8,7) - 1 - - """ - (b, x) = extended_euclid(a, n) - if b < 0: - b = (b % n + n) % n - return b - - -# Same a above using InvertingModulo -def chinese_remainder_theorem2(n1, r1, n2, r2): - """ - >>> chinese_remainder_theorem2(5,1,7,3) - 31 - - >>> chinese_remainder_theorem2(6,1,4,3) - 14 - - """ - x, y = invert_modulo(n1, n2), invert_modulo(n2, n1) - m = n1 * n2 - n = r2 * x * n1 + r1 * y * n2 - return (n % m + m) % m - - -# import testmod for testing our function -from doctest import testmod - -if __name__ == '__main__': - testmod(name='chinese_remainder_theorem', verbose=True) - testmod(name='chinese_remainder_theorem2', verbose=True) - testmod(name='invert_modulo', verbose=True) - testmod(name='extended_euclid', verbose=True) diff --git a/data_structures/hashing/number_theory/diophantine_equation.py b/data_structures/hashing/number_theory/diophantine_equation.py deleted file mode 100644 index 3ac7094eed6b..000000000000 --- a/data_structures/hashing/number_theory/diophantine_equation.py +++ /dev/null @@ -1,124 +0,0 @@ -# Diophantine Equation : Given integers a,b,c ( at least one of a and b != 0), the diophantine equation -# a*x + b*y = c has a solution (where x and y are integers) iff gcd(a,b) divides c. - -# GCD ( Greatest Common Divisor ) or HCF ( Highest Common Factor ) - - -def diophantine(a, b, c): - """ - >>> diophantine(10,6,14) - (-7.0, 14.0) - - >>> diophantine(391,299,-69) - (9.0, -12.0) - - But above equation has one more solution i.e., x = -4, y = 5. - That's why we need diophantine all solution function. - - """ - - assert c % greatest_common_divisor(a, b) == 0 # greatest_common_divisor(a,b) function implemented below - (d, x, y) = extended_gcd(a, b) # extended_gcd(a,b) function implemented below - r = c / d - return (r * x, r * y) - - -# Lemma : if n|ab and gcd(a,n) = 1, then n|b. - -# Finding All solutions of Diophantine Equations: - -# Theorem : Let gcd(a,b) = d, a = d*p, b = d*q. If (x0,y0) is a solution of Diophantine Equation a*x + b*y = c. -# a*x0 + b*y0 = c, then all the solutions have the form a(x0 + t*q) + b(y0 - t*p) = c, where t is an arbitrary integer. - -# n is the number of solution you want, n = 2 by default - -def diophantine_all_soln(a, b, c, n=2): - """ - >>> diophantine_all_soln(10, 6, 14) - -7.0 14.0 - -4.0 9.0 - - >>> diophantine_all_soln(10, 6, 14, 4) - -7.0 14.0 - -4.0 9.0 - -1.0 4.0 - 2.0 -1.0 - - >>> diophantine_all_soln(391, 299, -69, n = 4) - 9.0 -12.0 - 22.0 -29.0 - 35.0 -46.0 - 48.0 -63.0 - - """ - (x0, y0) = diophantine(a, b, c) # Initial value - d = greatest_common_divisor(a, b) - p = a // d - q = b // d - - for i in range(n): - x = x0 + i * q - y = y0 - i * p - print(x, y) - - -# Euclid's Lemma : d divides a and b, if and only if d divides a-b and b - -# Euclid's Algorithm - -def greatest_common_divisor(a, b): - """ - >>> greatest_common_divisor(7,5) - 1 - - Note : In number theory, two integers a and b are said to be relatively prime, mutually prime, or co-prime - if the only positive integer (factor) that divides both of them is 1 i.e., gcd(a,b) = 1. - - >>> greatest_common_divisor(121, 11) - 11 - - """ - if a < b: - a, b = b, a - - while a % b != 0: - a, b = b, a % b - - return b - - -# Extended Euclid's Algorithm : If d divides a and b and d = a*x + b*y for integers x and y, then d = gcd(a,b) - - -def extended_gcd(a, b): - """ - >>> extended_gcd(10, 6) - (2, -1, 2) - - >>> extended_gcd(7, 5) - (1, -2, 3) - - """ - assert a >= 0 and b >= 0 - - if b == 0: - d, x, y = a, 1, 0 - else: - (d, p, q) = extended_gcd(b, a % b) - x = q - y = p - q * (a // b) - - assert a % d == 0 and b % d == 0 - assert d == a * x + b * y - - return (d, x, y) - - -# import testmod for testing our function -from doctest import testmod - -if __name__ == '__main__': - testmod(name='diophantine', verbose=True) - testmod(name='diophantine_all_soln', verbose=True) - testmod(name='extended_gcd', verbose=True) - testmod(name='greatest_common_divisor', verbose=True) diff --git a/data_structures/hashing/number_theory/modular_division.py b/data_structures/hashing/number_theory/modular_division.py deleted file mode 100644 index 4e1623fbe923..000000000000 --- a/data_structures/hashing/number_theory/modular_division.py +++ /dev/null @@ -1,149 +0,0 @@ -# Modular Division : -# An efficient algorithm for dividing b by a modulo n. - -# GCD ( Greatest Common Divisor ) or HCF ( Highest Common Factor ) - -# Given three integers a, b, and n, such that gcd(a,n)=1 and n>1, the algorithm should return an integer x such that -# 0≤x≤n−1, and b/a=x(modn) (that is, b=ax(modn)). - -# Theorem: -# a has a multiplicative inverse modulo n iff gcd(a,n) = 1 - - -# This find x = b*a^(-1) mod n -# Uses ExtendedEuclid to find the inverse of a - - -def modular_division(a, b, n): - """ - >>> modular_division(4,8,5) - 2 - - >>> modular_division(3,8,5) - 1 - - >>> modular_division(4, 11, 5) - 4 - - """ - assert n > 1 and a > 0 and greatest_common_divisor(a, n) == 1 - (d, t, s) = extended_gcd(n, a) # Implemented below - x = (b * s) % n - return x - - -# This function find the inverses of a i.e., a^(-1) -def invert_modulo(a, n): - """ - >>> invert_modulo(2, 5) - 3 - - >>> invert_modulo(8,7) - 1 - - """ - (b, x) = extended_euclid(a, n) # Implemented below - if b < 0: - b = (b % n + n) % n - return b - - -# ------------------ Finding Modular division using invert_modulo ------------------- - -# This function used the above inversion of a to find x = (b*a^(-1))mod n -def modular_division2(a, b, n): - """ - >>> modular_division2(4,8,5) - 2 - - >>> modular_division2(3,8,5) - 1 - - >>> modular_division2(4, 11, 5) - 4 - - """ - s = invert_modulo(a, n) - x = (b * s) % n - return x - - -# Extended Euclid's Algorithm : If d divides a and b and d = a*x + b*y for integers x and y, then d = gcd(a,b) - -def extended_gcd(a, b): - """ - >>> extended_gcd(10, 6) - (2, -1, 2) - - >>> extended_gcd(7, 5) - (1, -2, 3) - - ** extended_gcd function is used when d = gcd(a,b) is required in output - - """ - assert a >= 0 and b >= 0 - - if b == 0: - d, x, y = a, 1, 0 - else: - (d, p, q) = extended_gcd(b, a % b) - x = q - y = p - q * (a // b) - - assert a % d == 0 and b % d == 0 - assert d == a * x + b * y - - return (d, x, y) - - -# Extended Euclid -def extended_euclid(a, b): - """ - >>> extended_euclid(10, 6) - (-1, 2) - - >>> extended_euclid(7, 5) - (-2, 3) - - """ - if b == 0: - return (1, 0) - (x, y) = extended_euclid(b, a % b) - k = a // b - return (y, x - k * y) - - -# Euclid's Lemma : d divides a and b, if and only if d divides a-b and b -# Euclid's Algorithm - -def greatest_common_divisor(a, b): - """ - >>> greatest_common_divisor(7,5) - 1 - - Note : In number theory, two integers a and b are said to be relatively prime, mutually prime, or co-prime - if the only positive integer (factor) that divides both of them is 1 i.e., gcd(a,b) = 1. - - >>> greatest_common_divisor(121, 11) - 11 - - """ - if a < b: - a, b = b, a - - while a % b != 0: - a, b = b, a % b - - return b - - -# Import testmod for testing our function -from doctest import testmod - -if __name__ == '__main__': - testmod(name='modular_division', verbose=True) - testmod(name='modular_division2', verbose=True) - testmod(name='invert_modulo', verbose=True) - testmod(name='extended_gcd', verbose=True) - testmod(name='extended_euclid', verbose=True) - testmod(name='greatest_common_divisor', verbose=True) From b2417013fd414d2f111b363b5938fe1a439c6060 Mon Sep 17 00:00:00 2001 From: OddExtension5 Date: Thu, 3 Oct 2019 17:35:58 +0530 Subject: [PATCH 11/11] added a new directory named blockchain & a files from data_structures/hashing/number_theory --- blockchain/chinese_remainder_theorem.py | 91 +++++++++++++++ blockchain/diophantine_equation.py | 124 ++++++++++++++++++++ blockchain/modular_division.py | 149 ++++++++++++++++++++++++ 3 files changed, 364 insertions(+) create mode 100644 blockchain/chinese_remainder_theorem.py create mode 100644 blockchain/diophantine_equation.py create mode 100644 blockchain/modular_division.py diff --git a/blockchain/chinese_remainder_theorem.py b/blockchain/chinese_remainder_theorem.py new file mode 100644 index 000000000000..f1409530a70e --- /dev/null +++ b/blockchain/chinese_remainder_theorem.py @@ -0,0 +1,91 @@ +# Chinese Remainder Theorem: +# GCD ( Greatest Common Divisor ) or HCF ( Highest Common Factor ) + +# If GCD(a,b) = 1, then for any remainder ra modulo a and any remainder rb modulo b there exists integer n, +# such that n = ra (mod a) and n = ra(mod b). If n1 and n2 are two such integers, then n1=n2(mod ab) + +# Algorithm : + +# 1. Use extended euclid algorithm to find x,y such that a*x + b*y = 1 +# 2. Take n = ra*by + rb*ax + + +# Extended Euclid +def extended_euclid(a, b): + """ + >>> extended_euclid(10, 6) + (-1, 2) + + >>> extended_euclid(7, 5) + (-2, 3) + + """ + if b == 0: + return (1, 0) + (x, y) = extended_euclid(b, a % b) + k = a // b + return (y, x - k * y) + + +# Uses ExtendedEuclid to find inverses +def chinese_remainder_theorem(n1, r1, n2, r2): + """ + >>> chinese_remainder_theorem(5,1,7,3) + 31 + + Explanation : 31 is the smallest number such that + (i) When we divide it by 5, we get remainder 1 + (ii) When we divide it by 7, we get remainder 3 + + >>> chinese_remainder_theorem(6,1,4,3) + 14 + + """ + (x, y) = extended_euclid(n1, n2) + m = n1 * n2 + n = r2 * x * n1 + r1 * y * n2 + return ((n % m + m) % m) + + +# ----------SAME SOLUTION USING InvertModulo instead ExtendedEuclid---------------- + +# This function find the inverses of a i.e., a^(-1) +def invert_modulo(a, n): + """ + >>> invert_modulo(2, 5) + 3 + + >>> invert_modulo(8,7) + 1 + + """ + (b, x) = extended_euclid(a, n) + if b < 0: + b = (b % n + n) % n + return b + + +# Same a above using InvertingModulo +def chinese_remainder_theorem2(n1, r1, n2, r2): + """ + >>> chinese_remainder_theorem2(5,1,7,3) + 31 + + >>> chinese_remainder_theorem2(6,1,4,3) + 14 + + """ + x, y = invert_modulo(n1, n2), invert_modulo(n2, n1) + m = n1 * n2 + n = r2 * x * n1 + r1 * y * n2 + return (n % m + m) % m + + +# import testmod for testing our function +from doctest import testmod + +if __name__ == '__main__': + testmod(name='chinese_remainder_theorem', verbose=True) + testmod(name='chinese_remainder_theorem2', verbose=True) + testmod(name='invert_modulo', verbose=True) + testmod(name='extended_euclid', verbose=True) diff --git a/blockchain/diophantine_equation.py b/blockchain/diophantine_equation.py new file mode 100644 index 000000000000..3ac7094eed6b --- /dev/null +++ b/blockchain/diophantine_equation.py @@ -0,0 +1,124 @@ +# Diophantine Equation : Given integers a,b,c ( at least one of a and b != 0), the diophantine equation +# a*x + b*y = c has a solution (where x and y are integers) iff gcd(a,b) divides c. + +# GCD ( Greatest Common Divisor ) or HCF ( Highest Common Factor ) + + +def diophantine(a, b, c): + """ + >>> diophantine(10,6,14) + (-7.0, 14.0) + + >>> diophantine(391,299,-69) + (9.0, -12.0) + + But above equation has one more solution i.e., x = -4, y = 5. + That's why we need diophantine all solution function. + + """ + + assert c % greatest_common_divisor(a, b) == 0 # greatest_common_divisor(a,b) function implemented below + (d, x, y) = extended_gcd(a, b) # extended_gcd(a,b) function implemented below + r = c / d + return (r * x, r * y) + + +# Lemma : if n|ab and gcd(a,n) = 1, then n|b. + +# Finding All solutions of Diophantine Equations: + +# Theorem : Let gcd(a,b) = d, a = d*p, b = d*q. If (x0,y0) is a solution of Diophantine Equation a*x + b*y = c. +# a*x0 + b*y0 = c, then all the solutions have the form a(x0 + t*q) + b(y0 - t*p) = c, where t is an arbitrary integer. + +# n is the number of solution you want, n = 2 by default + +def diophantine_all_soln(a, b, c, n=2): + """ + >>> diophantine_all_soln(10, 6, 14) + -7.0 14.0 + -4.0 9.0 + + >>> diophantine_all_soln(10, 6, 14, 4) + -7.0 14.0 + -4.0 9.0 + -1.0 4.0 + 2.0 -1.0 + + >>> diophantine_all_soln(391, 299, -69, n = 4) + 9.0 -12.0 + 22.0 -29.0 + 35.0 -46.0 + 48.0 -63.0 + + """ + (x0, y0) = diophantine(a, b, c) # Initial value + d = greatest_common_divisor(a, b) + p = a // d + q = b // d + + for i in range(n): + x = x0 + i * q + y = y0 - i * p + print(x, y) + + +# Euclid's Lemma : d divides a and b, if and only if d divides a-b and b + +# Euclid's Algorithm + +def greatest_common_divisor(a, b): + """ + >>> greatest_common_divisor(7,5) + 1 + + Note : In number theory, two integers a and b are said to be relatively prime, mutually prime, or co-prime + if the only positive integer (factor) that divides both of them is 1 i.e., gcd(a,b) = 1. + + >>> greatest_common_divisor(121, 11) + 11 + + """ + if a < b: + a, b = b, a + + while a % b != 0: + a, b = b, a % b + + return b + + +# Extended Euclid's Algorithm : If d divides a and b and d = a*x + b*y for integers x and y, then d = gcd(a,b) + + +def extended_gcd(a, b): + """ + >>> extended_gcd(10, 6) + (2, -1, 2) + + >>> extended_gcd(7, 5) + (1, -2, 3) + + """ + assert a >= 0 and b >= 0 + + if b == 0: + d, x, y = a, 1, 0 + else: + (d, p, q) = extended_gcd(b, a % b) + x = q + y = p - q * (a // b) + + assert a % d == 0 and b % d == 0 + assert d == a * x + b * y + + return (d, x, y) + + +# import testmod for testing our function +from doctest import testmod + +if __name__ == '__main__': + testmod(name='diophantine', verbose=True) + testmod(name='diophantine_all_soln', verbose=True) + testmod(name='extended_gcd', verbose=True) + testmod(name='greatest_common_divisor', verbose=True) diff --git a/blockchain/modular_division.py b/blockchain/modular_division.py new file mode 100644 index 000000000000..4e1623fbe923 --- /dev/null +++ b/blockchain/modular_division.py @@ -0,0 +1,149 @@ +# Modular Division : +# An efficient algorithm for dividing b by a modulo n. + +# GCD ( Greatest Common Divisor ) or HCF ( Highest Common Factor ) + +# Given three integers a, b, and n, such that gcd(a,n)=1 and n>1, the algorithm should return an integer x such that +# 0≤x≤n−1, and b/a=x(modn) (that is, b=ax(modn)). + +# Theorem: +# a has a multiplicative inverse modulo n iff gcd(a,n) = 1 + + +# This find x = b*a^(-1) mod n +# Uses ExtendedEuclid to find the inverse of a + + +def modular_division(a, b, n): + """ + >>> modular_division(4,8,5) + 2 + + >>> modular_division(3,8,5) + 1 + + >>> modular_division(4, 11, 5) + 4 + + """ + assert n > 1 and a > 0 and greatest_common_divisor(a, n) == 1 + (d, t, s) = extended_gcd(n, a) # Implemented below + x = (b * s) % n + return x + + +# This function find the inverses of a i.e., a^(-1) +def invert_modulo(a, n): + """ + >>> invert_modulo(2, 5) + 3 + + >>> invert_modulo(8,7) + 1 + + """ + (b, x) = extended_euclid(a, n) # Implemented below + if b < 0: + b = (b % n + n) % n + return b + + +# ------------------ Finding Modular division using invert_modulo ------------------- + +# This function used the above inversion of a to find x = (b*a^(-1))mod n +def modular_division2(a, b, n): + """ + >>> modular_division2(4,8,5) + 2 + + >>> modular_division2(3,8,5) + 1 + + >>> modular_division2(4, 11, 5) + 4 + + """ + s = invert_modulo(a, n) + x = (b * s) % n + return x + + +# Extended Euclid's Algorithm : If d divides a and b and d = a*x + b*y for integers x and y, then d = gcd(a,b) + +def extended_gcd(a, b): + """ + >>> extended_gcd(10, 6) + (2, -1, 2) + + >>> extended_gcd(7, 5) + (1, -2, 3) + + ** extended_gcd function is used when d = gcd(a,b) is required in output + + """ + assert a >= 0 and b >= 0 + + if b == 0: + d, x, y = a, 1, 0 + else: + (d, p, q) = extended_gcd(b, a % b) + x = q + y = p - q * (a // b) + + assert a % d == 0 and b % d == 0 + assert d == a * x + b * y + + return (d, x, y) + + +# Extended Euclid +def extended_euclid(a, b): + """ + >>> extended_euclid(10, 6) + (-1, 2) + + >>> extended_euclid(7, 5) + (-2, 3) + + """ + if b == 0: + return (1, 0) + (x, y) = extended_euclid(b, a % b) + k = a // b + return (y, x - k * y) + + +# Euclid's Lemma : d divides a and b, if and only if d divides a-b and b +# Euclid's Algorithm + +def greatest_common_divisor(a, b): + """ + >>> greatest_common_divisor(7,5) + 1 + + Note : In number theory, two integers a and b are said to be relatively prime, mutually prime, or co-prime + if the only positive integer (factor) that divides both of them is 1 i.e., gcd(a,b) = 1. + + >>> greatest_common_divisor(121, 11) + 11 + + """ + if a < b: + a, b = b, a + + while a % b != 0: + a, b = b, a % b + + return b + + +# Import testmod for testing our function +from doctest import testmod + +if __name__ == '__main__': + testmod(name='modular_division', verbose=True) + testmod(name='modular_division2', verbose=True) + testmod(name='invert_modulo', verbose=True) + testmod(name='extended_gcd', verbose=True) + testmod(name='extended_euclid', verbose=True) + testmod(name='greatest_common_divisor', verbose=True)