From 86d7e09df391d45b21b25a7f78e08e3e90270ef7 Mon Sep 17 00:00:00 2001 From: Joyce Date: Fri, 2 Oct 2020 07:39:40 +0800 Subject: [PATCH 1/6] add type hints to math/extended euclid --- maths/extended_euclidean_algorithm.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/maths/extended_euclidean_algorithm.py b/maths/extended_euclidean_algorithm.py index fe81bcfaf71d..b39a58e965c7 100644 --- a/maths/extended_euclidean_algorithm.py +++ b/maths/extended_euclidean_algorithm.py @@ -14,7 +14,7 @@ import sys -def extended_euclidean_algorithm(m, n): +def extended_euclidean_algorithm(m: int, n: int) -> (int, int): """ Extended Euclidean Algorithm. From c57736ef964ded7bd3b958caa124667afb1bfcf3 Mon Sep 17 00:00:00 2001 From: Joyce Date: Fri, 2 Oct 2020 07:50:41 +0800 Subject: [PATCH 2/6] math/extended euclid - add doctest --- maths/extended_euclidean_algorithm.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/maths/extended_euclidean_algorithm.py b/maths/extended_euclidean_algorithm.py index b39a58e965c7..ac548f802a6c 100644 --- a/maths/extended_euclidean_algorithm.py +++ b/maths/extended_euclidean_algorithm.py @@ -20,6 +20,12 @@ def extended_euclidean_algorithm(m: int, n: int) -> (int, int): Finds 2 numbers a and b such that it satisfies the equation am + bn = gcd(m, n) (a.k.a Bezout's Identity) + + >>> extended_euclidean_algorithm(1, 24) + (1, 0) + + >>> extended_euclidean_algorithm(8, 14) + (2, -1) """ a = 0 a_prime = 1 @@ -69,4 +75,7 @@ def main(): if __name__ == "__main__": + import doctest + + doctest.testmod() main() From cea02d9286f1b2612a44afca2b5f8945c686dd58 Mon Sep 17 00:00:00 2001 From: Joyce Date: Fri, 2 Oct 2020 08:10:33 +0800 Subject: [PATCH 3/6] math/extended euclid: remove manual doctest --- maths/extended_euclidean_algorithm.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/maths/extended_euclidean_algorithm.py b/maths/extended_euclidean_algorithm.py index ac548f802a6c..e72bc300d56f 100644 --- a/maths/extended_euclidean_algorithm.py +++ b/maths/extended_euclidean_algorithm.py @@ -75,7 +75,4 @@ def main(): if __name__ == "__main__": - import doctest - - doctest.testmod() main() From 478b0ac50ea5c8d014723f1cc0816ff8500c9d65 Mon Sep 17 00:00:00 2001 From: Joyce Date: Fri, 2 Oct 2020 14:16:38 +0800 Subject: [PATCH 4/6] change algorithm for negative numbers --- maths/extended_euclidean_algorithm.py | 102 ++++++++++++++++---------- 1 file changed, 62 insertions(+), 40 deletions(-) diff --git a/maths/extended_euclidean_algorithm.py b/maths/extended_euclidean_algorithm.py index e72bc300d56f..2e14683c0977 100644 --- a/maths/extended_euclidean_algorithm.py +++ b/maths/extended_euclidean_algorithm.py @@ -3,18 +3,42 @@ Finds 2 numbers a and b such that it satisfies the equation am + bn = gcd(m, n) (a.k.a Bezout's Identity) + +https://en.wikipedia.org/wiki/Extended_Euclidean_algorithm """ # @Author: S. Sharma # @Date: 2019-02-25T12:08:53-06:00 # @Email: silentcat@protonmail.com -# @Last modified by: PatOnTheBack -# @Last modified time: 2019-07-05 +# @Last modified by: pikulet +# @Last modified time: 2020-10-02 import sys -def extended_euclidean_algorithm(m: int, n: int) -> (int, int): +def sign(n: int) -> int: + """ + Returns sign of number for correction of negative numbers in algorithm + + >>> sign(4) + 1 + + >>> sign(0) + 0 + + >>> sign(-8) + -1 + + """ + if n > 0: + return 1 + elif n < 0: + return -1 + else: + return 0 + + +def extended_euclidean_algorithm(a: int, b: int) -> (int, int): """ Extended Euclidean Algorithm. @@ -26,42 +50,40 @@ def extended_euclidean_algorithm(m: int, n: int) -> (int, int): >>> extended_euclidean_algorithm(8, 14) (2, -1) + + >>> extended_euclidean_algorithm(240, 46) + (-9, 47) + + >>> extended_euclidean_algorithm(1, -4) + (1, 0) + + >>> extended_euclidean_algorithm(-2, -4) + (-1, 0) + + >>> extended_euclidean_algorithm(0, -4) + (0, -1) + + >>> extended_euclidean_algorithm(2, 0) + (1, 0) + """ - a = 0 - a_prime = 1 - b = 1 - b_prime = 0 - q = 0 - r = 0 - if m > n: - c = m - d = n - else: - c = n - d = m - - while True: - q = int(c / d) - r = c % d - if r == 0: - break - c = d - d = r - - t = a_prime - a_prime = a - a = t - q * a - - t = b_prime - b_prime = b - b = t - q * b - - pair = None - if m > n: - pair = (a, b) + old_r, r = a, b + old_s, s = 1, 0 + old_t, t = 0, 1 + + while r != 0: + quotient = old_r // r + old_r, r = r, old_r - quotient * r + old_s, s = s, old_s - quotient * s + old_t, t = t, old_t - quotient * t + + # sign correction for negative numbers + if abs(a) == 1: + return sign(a), 0 + elif abs(b) == 1: + return 0, sign(b) else: - pair = (b, a) - return pair + return (sign(a) * old_s, sign(b) * old_t) def main(): @@ -69,9 +91,9 @@ def main(): if len(sys.argv) < 3: print("2 integer arguments required") exit(1) - m = int(sys.argv[1]) - n = int(sys.argv[2]) - print(extended_euclidean_algorithm(m, n)) + a = int(sys.argv[1]) + b = int(sys.argv[2]) + print(extended_euclidean_algorithm(a, b)) if __name__ == "__main__": From 9db6f67ef2c8c81fb97c29804c8db641b60763d2 Mon Sep 17 00:00:00 2001 From: Joyce Date: Wed, 7 Oct 2020 16:32:58 +0800 Subject: [PATCH 5/6] improve naming of variables --- maths/extended_euclidean_algorithm.py | 56 ++++++++++----------------- 1 file changed, 20 insertions(+), 36 deletions(-) diff --git a/maths/extended_euclidean_algorithm.py b/maths/extended_euclidean_algorithm.py index 2e14683c0977..13261a616bac 100644 --- a/maths/extended_euclidean_algorithm.py +++ b/maths/extended_euclidean_algorithm.py @@ -16,28 +16,6 @@ import sys -def sign(n: int) -> int: - """ - Returns sign of number for correction of negative numbers in algorithm - - >>> sign(4) - 1 - - >>> sign(0) - 0 - - >>> sign(-8) - -1 - - """ - if n > 0: - return 1 - elif n < 0: - return -1 - else: - return 0 - - def extended_euclidean_algorithm(a: int, b: int) -> (int, int): """ Extended Euclidean Algorithm. @@ -67,23 +45,29 @@ def extended_euclidean_algorithm(a: int, b: int) -> (int, int): (1, 0) """ - old_r, r = a, b - old_s, s = 1, 0 - old_t, t = 0, 1 + # base cases + if abs(a) == 1: + return a, 0 + elif abs(b) == 1: + return 0, b + + old_remainder, remainder = a, b + old_coeff_a, coeff_a = 1, 0 + old_coeff_b, coeff_b = 0, 1 - while r != 0: - quotient = old_r // r - old_r, r = r, old_r - quotient * r - old_s, s = s, old_s - quotient * s - old_t, t = t, old_t - quotient * t + while remainder != 0: + quotient = old_remainder // remainder + old_remainder, remainder = remainder, old_remainder - quotient * remainder + old_coeff_a, coeff_a = coeff_a, old_coeff_a - quotient * coeff_a + old_coeff_b, coeff_b = coeff_b, old_coeff_b - quotient * coeff_b # sign correction for negative numbers - if abs(a) == 1: - return sign(a), 0 - elif abs(b) == 1: - return 0, sign(b) - else: - return (sign(a) * old_s, sign(b) * old_t) + if a < 0: + old_coeff_a = -old_coeff_a + if b < 0: + old_coeff_b = -old_coeff_b + + return old_coeff_a, old_coeff_b def main(): From b00b63d097c7535a0c931f82f806dc3cbc93ee8b Mon Sep 17 00:00:00 2001 From: Dhruv Date: Wed, 7 Oct 2020 15:17:39 +0530 Subject: [PATCH 6/6] Update extended_euclidean_algorithm.py --- maths/extended_euclidean_algorithm.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/maths/extended_euclidean_algorithm.py b/maths/extended_euclidean_algorithm.py index 13261a616bac..e7087636ce09 100644 --- a/maths/extended_euclidean_algorithm.py +++ b/maths/extended_euclidean_algorithm.py @@ -14,9 +14,10 @@ # @Last modified time: 2020-10-02 import sys +from typing import Tuple -def extended_euclidean_algorithm(a: int, b: int) -> (int, int): +def extended_euclidean_algorithm(a: int, b: int) -> Tuple[int, int]: """ Extended Euclidean Algorithm.