From 5b6889e1d36a5d6241b268385036113d3a3d6968 Mon Sep 17 00:00:00 2001 From: Siddikpatel Date: Mon, 2 Oct 2023 10:21:23 +0530 Subject: [PATCH 01/11] Deleted greatest_common_divisor def from many files and instead imported the method from Maths folder --- blockchain/diophantine_equation.py | 30 ++----------------------- blockchain/modular_division.py | 26 +--------------------- ciphers/hill_cipher.py | 15 +------------ maths/greatest_common_divisor.py | 35 ++++++++++-------------------- maths/least_common_multiple.py | 21 +----------------- project_euler/problem_005/sol2.py | 19 ++-------------- 6 files changed, 18 insertions(+), 128 deletions(-) diff --git a/blockchain/diophantine_equation.py b/blockchain/diophantine_equation.py index 22b0cad75c63..b9a92c9d3364 100644 --- a/blockchain/diophantine_equation.py +++ b/blockchain/diophantine_equation.py @@ -1,4 +1,5 @@ from __future__ import annotations +from maths.greatest_common_divisor import greatest_common_divisor def diophantine(a: int, b: int, c: int) -> tuple[float, float]: @@ -22,7 +23,7 @@ def diophantine(a: int, b: int, c: int) -> tuple[float, float]: assert ( c % greatest_common_divisor(a, b) == 0 - ) # greatest_common_divisor(a,b) function implemented below + ) # greatest_common_divisor(a,b) is in Algorithms' directory's gcd file (d, x, y) = extended_gcd(a, b) # extended_gcd(a,b) function implemented below r = c / d return (r * x, r * y) @@ -68,33 +69,6 @@ def diophantine_all_soln(a: int, b: int, c: int, n: int = 2) -> None: y = y0 - i * p print(x, y) - -def greatest_common_divisor(a: int, b: int) -> int: - """ - Euclid's Lemma : d divides a and b, if and only if d divides a-b and b - - Euclid's Algorithm - - >>> 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 - - def extended_gcd(a: int, b: int) -> tuple[int, int, int]: """ Extended Euclid's Algorithm : If d divides a and b and d = a*x + b*y for integers diff --git a/blockchain/modular_division.py b/blockchain/modular_division.py index a9d0f65c5b27..b94d695aef24 100644 --- a/blockchain/modular_division.py +++ b/blockchain/modular_division.py @@ -1,4 +1,5 @@ from __future__ import annotations +from maths.greatest_common_divisor import greatest_common_divisor def modular_division(a: int, b: int, n: int) -> int: @@ -118,31 +119,6 @@ def extended_euclid(a: int, b: int) -> tuple[int, int]: return (y, x - k * y) -def greatest_common_divisor(a: int, b: int) -> int: - """ - Euclid's Lemma : d divides a and b, if and only if d divides a-b and b - Euclid's Algorithm - - >>> 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 - - if __name__ == "__main__": from doctest import testmod diff --git a/ciphers/hill_cipher.py b/ciphers/hill_cipher.py index b4424e82298e..1501f81319bb 100644 --- a/ciphers/hill_cipher.py +++ b/ciphers/hill_cipher.py @@ -36,24 +36,11 @@ """ import string +from maths.greatest_common_divisor import greatest_common_divisor import numpy -def greatest_common_divisor(a: int, b: int) -> int: - """ - >>> greatest_common_divisor(4, 8) - 4 - >>> greatest_common_divisor(8, 4) - 4 - >>> greatest_common_divisor(4, 7) - 1 - >>> greatest_common_divisor(0, 10) - 10 - """ - return b if a == 0 else greatest_common_divisor(b % a, a) - - class HillCipher: key_string = string.ascii_uppercase + string.digits # This cipher takes alphanumerics into account diff --git a/maths/greatest_common_divisor.py b/maths/greatest_common_divisor.py index a2174a8eb74a..3cb70b5eaa29 100644 --- a/maths/greatest_common_divisor.py +++ b/maths/greatest_common_divisor.py @@ -1,38 +1,25 @@ """ Greatest Common Divisor. -Wikipedia reference: https://en.wikipedia.org/wiki/Greatest_common_divisor +Wikipedia reference: https://en.wikipedia.org/wiki/greatest_common_divisor gcd(a, b) = gcd(a, -b) = gcd(-a, b) = gcd(-a, -b) by definition of divisibility """ - def greatest_common_divisor(a: int, b: int) -> int: """ - Calculate Greatest Common Divisor (GCD). - >>> greatest_common_divisor(24, 40) - 8 - >>> greatest_common_divisor(1, 1) - 1 - >>> greatest_common_divisor(1, 800) - 1 - >>> greatest_common_divisor(11, 37) - 1 - >>> greatest_common_divisor(3, 5) - 1 - >>> greatest_common_divisor(16, 4) + >>> greatest_common_divisor(4, 8) 4 - >>> greatest_common_divisor(-3, 9) - 3 - >>> greatest_common_divisor(9, -3) - 3 - >>> greatest_common_divisor(3, -9) - 3 - >>> greatest_common_divisor(-3, -9) - 3 + >>> greatest_common_divisor(8, 4) + 4 + >>> greatest_common_divisor(4, 7) + 1 + >>> greatest_common_divisor(0, 10) + 10 """ - return abs(b) if a == 0 else greatest_common_divisor(b % a, a) - + if a == 0: + return b + greatest_common_divisor(b % a, a) def gcd_by_iterative(x: int, y: int) -> int: """ diff --git a/maths/least_common_multiple.py b/maths/least_common_multiple.py index 10cc63ac7990..57c58ace7b4b 100644 --- a/maths/least_common_multiple.py +++ b/maths/least_common_multiple.py @@ -1,5 +1,6 @@ import unittest from timeit import timeit +from maths.greatest_common_divisor import greatest_common_divisor def least_common_multiple_slow(first_num: int, second_num: int) -> int: @@ -20,26 +21,6 @@ def least_common_multiple_slow(first_num: int, second_num: int) -> int: return common_mult -def greatest_common_divisor(a: int, b: int) -> int: - """ - Calculate Greatest Common Divisor (GCD). - see greatest_common_divisor.py - >>> greatest_common_divisor(24, 40) - 8 - >>> greatest_common_divisor(1, 1) - 1 - >>> greatest_common_divisor(1, 800) - 1 - >>> greatest_common_divisor(11, 37) - 1 - >>> greatest_common_divisor(3, 5) - 1 - >>> greatest_common_divisor(16, 4) - 4 - """ - return b if a == 0 else greatest_common_divisor(b % a, a) - - def least_common_multiple_fast(first_num: int, second_num: int) -> int: """ Find the least common multiple of two numbers. diff --git a/project_euler/problem_005/sol2.py b/project_euler/problem_005/sol2.py index 1b3e5e130f03..4558e21fd0f0 100644 --- a/project_euler/problem_005/sol2.py +++ b/project_euler/problem_005/sol2.py @@ -1,3 +1,5 @@ +from maths.greatest_common_divisor import greatest_common_divisor + """ Project Euler Problem 5: https://projecteuler.net/problem=5 @@ -16,23 +18,6 @@ """ -def greatest_common_divisor(x: int, y: int) -> int: - """ - Euclidean Greatest Common Divisor algorithm - - >>> greatest_common_divisor(0, 0) - 0 - >>> greatest_common_divisor(23, 42) - 1 - >>> greatest_common_divisor(15, 33) - 3 - >>> greatest_common_divisor(12345, 67890) - 15 - """ - - return x if y == 0 else greatest_common_divisor(y, x % y) - - def lcm(x: int, y: int) -> int: """ Least Common Multiple. From a98771c288274ac0cac737a8b29034f9ec17e911 Mon Sep 17 00:00:00 2001 From: Siddikpatel Date: Mon, 2 Oct 2023 10:32:52 +0530 Subject: [PATCH 02/11] Deleted greatest_common_divisor def from many files and instead imported the method from Maths folder, also fixed comments --- blockchain/diophantine_equation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/blockchain/diophantine_equation.py b/blockchain/diophantine_equation.py index b9a92c9d3364..ebb02233f2ec 100644 --- a/blockchain/diophantine_equation.py +++ b/blockchain/diophantine_equation.py @@ -23,7 +23,7 @@ def diophantine(a: int, b: int, c: int) -> tuple[float, float]: assert ( c % greatest_common_divisor(a, b) == 0 - ) # greatest_common_divisor(a,b) is in Algorithms' directory's gcd file + ) # greatest_common_divisor(a,b) is in maths directory (d, x, y) = extended_gcd(a, b) # extended_gcd(a,b) function implemented below r = c / d return (r * x, r * y) From 54aca90e61cd2f89faaa9b7d0d7818366a377eea Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 2 Oct 2023 05:04:53 +0000 Subject: [PATCH 03/11] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- blockchain/diophantine_equation.py | 1 + maths/greatest_common_divisor.py | 2 ++ 2 files changed, 3 insertions(+) diff --git a/blockchain/diophantine_equation.py b/blockchain/diophantine_equation.py index ebb02233f2ec..42661ea102fe 100644 --- a/blockchain/diophantine_equation.py +++ b/blockchain/diophantine_equation.py @@ -69,6 +69,7 @@ def diophantine_all_soln(a: int, b: int, c: int, n: int = 2) -> None: y = y0 - i * p print(x, y) + def extended_gcd(a: int, b: int) -> tuple[int, int, int]: """ Extended Euclid's Algorithm : If d divides a and b and d = a*x + b*y for integers diff --git a/maths/greatest_common_divisor.py b/maths/greatest_common_divisor.py index 3cb70b5eaa29..b9762eb1a821 100644 --- a/maths/greatest_common_divisor.py +++ b/maths/greatest_common_divisor.py @@ -6,6 +6,7 @@ gcd(a, b) = gcd(a, -b) = gcd(-a, b) = gcd(-a, -b) by definition of divisibility """ + def greatest_common_divisor(a: int, b: int) -> int: """ >>> greatest_common_divisor(4, 8) @@ -21,6 +22,7 @@ def greatest_common_divisor(a: int, b: int) -> int: return b greatest_common_divisor(b % a, a) + def gcd_by_iterative(x: int, y: int) -> int: """ Below method is more memory efficient because it does not create additional From 2b9524572d613bc9bd5e0a66f4071a39c47f0653 Mon Sep 17 00:00:00 2001 From: Siddikpatel Date: Mon, 2 Oct 2023 10:42:12 +0530 Subject: [PATCH 04/11] Deleted greatest_common_divisor def from many files and instead imported the method from Maths folder, also fixed comments --- maths/greatest_common_divisor.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/maths/greatest_common_divisor.py b/maths/greatest_common_divisor.py index 3cb70b5eaa29..f0b9ff98c412 100644 --- a/maths/greatest_common_divisor.py +++ b/maths/greatest_common_divisor.py @@ -17,9 +17,9 @@ def greatest_common_divisor(a: int, b: int) -> int: >>> greatest_common_divisor(0, 10) 10 """ - if a == 0: - return b - greatest_common_divisor(b % a, a) + while b: + a, b = b, a % b + return a def gcd_by_iterative(x: int, y: int) -> int: """ From 21b26646b1a552327eb7d4ce8afdc40619b3c7e3 Mon Sep 17 00:00:00 2001 From: Siddikpatel Date: Sun, 8 Oct 2023 07:37:30 +0530 Subject: [PATCH 05/11] Imports organized --- blockchain/diophantine_equation.py | 1 + blockchain/modular_division.py | 1 + ciphers/hill_cipher.py | 3 ++- maths/least_common_multiple.py | 1 + 4 files changed, 5 insertions(+), 1 deletion(-) diff --git a/blockchain/diophantine_equation.py b/blockchain/diophantine_equation.py index 42661ea102fe..a24ea3504b94 100644 --- a/blockchain/diophantine_equation.py +++ b/blockchain/diophantine_equation.py @@ -1,4 +1,5 @@ from __future__ import annotations + from maths.greatest_common_divisor import greatest_common_divisor diff --git a/blockchain/modular_division.py b/blockchain/modular_division.py index b94d695aef24..8e54bb67ca58 100644 --- a/blockchain/modular_division.py +++ b/blockchain/modular_division.py @@ -1,4 +1,5 @@ from __future__ import annotations + from maths.greatest_common_divisor import greatest_common_divisor diff --git a/ciphers/hill_cipher.py b/ciphers/hill_cipher.py index 1501f81319bb..1201fda901e5 100644 --- a/ciphers/hill_cipher.py +++ b/ciphers/hill_cipher.py @@ -36,10 +36,11 @@ """ import string -from maths.greatest_common_divisor import greatest_common_divisor import numpy +from maths.greatest_common_divisor import greatest_common_divisor + class HillCipher: key_string = string.ascii_uppercase + string.digits diff --git a/maths/least_common_multiple.py b/maths/least_common_multiple.py index 57c58ace7b4b..4f28da8ab2a7 100644 --- a/maths/least_common_multiple.py +++ b/maths/least_common_multiple.py @@ -1,5 +1,6 @@ import unittest from timeit import timeit + from maths.greatest_common_divisor import greatest_common_divisor From 92730e2f71e7f9fd3255702169d099ae9382ac44 Mon Sep 17 00:00:00 2001 From: Siddikpatel Date: Sun, 8 Oct 2023 09:57:31 +0530 Subject: [PATCH 06/11] recursive gcd function implementation rolledback --- maths/greatest_common_divisor.py | 33 +++++++++++++++++++++----------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/maths/greatest_common_divisor.py b/maths/greatest_common_divisor.py index b7016568fffa..a2174a8eb74a 100644 --- a/maths/greatest_common_divisor.py +++ b/maths/greatest_common_divisor.py @@ -1,7 +1,7 @@ """ Greatest Common Divisor. -Wikipedia reference: https://en.wikipedia.org/wiki/greatest_common_divisor +Wikipedia reference: https://en.wikipedia.org/wiki/Greatest_common_divisor gcd(a, b) = gcd(a, -b) = gcd(-a, b) = gcd(-a, -b) by definition of divisibility """ @@ -9,18 +9,29 @@ def greatest_common_divisor(a: int, b: int) -> int: """ - >>> greatest_common_divisor(4, 8) - 4 - >>> greatest_common_divisor(8, 4) - 4 - >>> greatest_common_divisor(4, 7) + Calculate Greatest Common Divisor (GCD). + >>> greatest_common_divisor(24, 40) + 8 + >>> greatest_common_divisor(1, 1) + 1 + >>> greatest_common_divisor(1, 800) + 1 + >>> greatest_common_divisor(11, 37) + 1 + >>> greatest_common_divisor(3, 5) 1 - >>> greatest_common_divisor(0, 10) - 10 + >>> greatest_common_divisor(16, 4) + 4 + >>> greatest_common_divisor(-3, 9) + 3 + >>> greatest_common_divisor(9, -3) + 3 + >>> greatest_common_divisor(3, -9) + 3 + >>> greatest_common_divisor(-3, -9) + 3 """ - while b: - a, b = b, a % b - return a + return abs(b) if a == 0 else greatest_common_divisor(b % a, a) def gcd_by_iterative(x: int, y: int) -> int: From 60ce5e854b1c2c3ec9fb2c6838fd82ea8e038059 Mon Sep 17 00:00:00 2001 From: Siddikpatel Date: Sun, 8 Oct 2023 10:27:50 +0530 Subject: [PATCH 07/11] more gcd duplicates removed --- blockchain/diophantine_equation.py | 2 +- ciphers/affine_cipher.py | 5 ++-- ciphers/cryptomath_module.py | 7 ++---- ciphers/rsa_key_generator.py | 3 ++- maths/carmichael_number.py | 13 +++------- maths/primelib.py | 39 +++--------------------------- 6 files changed, 14 insertions(+), 55 deletions(-) diff --git a/blockchain/diophantine_equation.py b/blockchain/diophantine_equation.py index a24ea3504b94..7110d90230c9 100644 --- a/blockchain/diophantine_equation.py +++ b/blockchain/diophantine_equation.py @@ -7,7 +7,7 @@ def diophantine(a: int, b: int, c: int) -> tuple[float, float]: """ 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. + iff greatest_common_divisor(a,b) divides c. GCD ( Greatest Common Divisor ) or HCF ( Highest Common Factor ) diff --git a/ciphers/affine_cipher.py b/ciphers/affine_cipher.py index cd1e33b88425..5010b13dd7aa 100644 --- a/ciphers/affine_cipher.py +++ b/ciphers/affine_cipher.py @@ -1,5 +1,6 @@ import random import sys +from maths.greatest_common_divisor import gcd_by_iterative from . import cryptomath_module as cryptomath @@ -26,7 +27,7 @@ def check_keys(key_a: int, key_b: int, mode: str) -> None: "Key A must be greater than 0 and key B must " f"be between 0 and {len(SYMBOLS) - 1}." ) - if cryptomath.gcd(key_a, len(SYMBOLS)) != 1: + if gcd_by_iterative(key_a, len(SYMBOLS)) != 1: sys.exit( f"Key A {key_a} and the symbol set size {len(SYMBOLS)} " "are not relatively prime. Choose a different key." @@ -76,7 +77,7 @@ def get_random_key() -> int: while True: key_b = random.randint(2, len(SYMBOLS)) key_b = random.randint(2, len(SYMBOLS)) - if cryptomath.gcd(key_b, len(SYMBOLS)) == 1 and key_b % len(SYMBOLS) != 0: + if gcd_by_iterative(key_b, len(SYMBOLS)) == 1 and key_b % len(SYMBOLS) != 0: return key_b * len(SYMBOLS) + key_b diff --git a/ciphers/cryptomath_module.py b/ciphers/cryptomath_module.py index 6f15f7b733e6..02e94e4b9e92 100644 --- a/ciphers/cryptomath_module.py +++ b/ciphers/cryptomath_module.py @@ -1,11 +1,8 @@ -def gcd(a: int, b: int) -> int: - while a != 0: - a, b = b % a, a - return b +from maths.greatest_common_divisor import gcd_by_iterative def find_mod_inverse(a: int, m: int) -> int: - if gcd(a, m) != 1: + if gcd_by_iterative(a, m) != 1: msg = f"mod inverse of {a!r} and {m!r} does not exist" raise ValueError(msg) u1, u2, u3 = 1, 0, a diff --git a/ciphers/rsa_key_generator.py b/ciphers/rsa_key_generator.py index eedc7336804a..ee35580f4d3d 100644 --- a/ciphers/rsa_key_generator.py +++ b/ciphers/rsa_key_generator.py @@ -1,6 +1,7 @@ import os import random import sys +from maths.greatest_common_divisor import gcd_by_iterative from . import cryptomath_module, rabin_miller @@ -27,7 +28,7 @@ def generate_key(key_size: int) -> tuple[tuple[int, int], tuple[int, int]]: # Generate e that is relatively prime to (p - 1) * (q - 1) while True: e = random.randrange(2 ** (key_size - 1), 2 ** (key_size)) - if cryptomath_module.gcd(e, (p - 1) * (q - 1)) == 1: + if gcd_by_iterative(e, (p - 1) * (q - 1)) == 1: break # Calculate d that is mod inverse of e diff --git a/maths/carmichael_number.py b/maths/carmichael_number.py index c9c144759246..4022c18490db 100644 --- a/maths/carmichael_number.py +++ b/maths/carmichael_number.py @@ -5,19 +5,12 @@ power(b, n-1) MOD n = 1, for all b ranging from 1 to n such that b and - n are relatively prime, i.e, gcd(b, n) = 1 + n are relatively prime, i.e, greatest_common_divisor(b, n) = 1 Examples of Carmichael Numbers: 561, 1105, ... https://en.wikipedia.org/wiki/Carmichael_number """ - - -def gcd(a: int, b: int) -> int: - if a < b: - return gcd(b, a) - if a % b == 0: - return b - return gcd(b, a % b) +from maths.greatest_common_divisor import greatest_common_divisor def power(x: int, y: int, mod: int) -> int: @@ -33,7 +26,7 @@ def power(x: int, y: int, mod: int) -> int: def is_carmichael_number(n: int) -> bool: b = 2 while b < n: - if gcd(b, n) == 1 and power(b, n - 1, n) != 1: + if greatest_common_divisor(b, n) == 1 and power(b, n - 1, n) != 1: return False b += 1 return True diff --git a/maths/primelib.py b/maths/primelib.py index 28b5aee9dcc8..b1edad1429ac 100644 --- a/maths/primelib.py +++ b/maths/primelib.py @@ -21,7 +21,6 @@ is_even(number) is_odd(number) -gcd(number1, number2) // greatest common divisor kg_v(number1, number2) // least common multiple get_divisors(number) // all divisors of 'number' inclusive 1, number is_perfect_number(number) @@ -39,6 +38,7 @@ """ from math import sqrt +from maths.greatest_common_divisor import gcd_by_iterative def is_prime(number: int) -> bool: @@ -317,39 +317,6 @@ def goldbach(number): # ---------------------------------------------- -def gcd(number1, number2): - """ - Greatest common divisor - input: two positive integer 'number1' and 'number2' - returns the greatest common divisor of 'number1' and 'number2' - """ - - # precondition - assert ( - isinstance(number1, int) - and isinstance(number2, int) - and (number1 >= 0) - and (number2 >= 0) - ), "'number1' and 'number2' must been positive integer." - - rest = 0 - - while number2 != 0: - rest = number1 % number2 - number1 = number2 - number2 = rest - - # precondition - assert isinstance(number1, int) and ( - number1 >= 0 - ), "'number' must been from type int and positive" - - return number1 - - -# ---------------------------------------------------- - - def kg_v(number1, number2): """ Least common multiple @@ -567,14 +534,14 @@ def simplify_fraction(numerator, denominator): ), "The arguments must been from type int and 'denominator' != 0" # build the greatest common divisor of numerator and denominator. - gcd_of_fraction = gcd(abs(numerator), abs(denominator)) + gcd_of_fraction = gcd_by_iterative(abs(numerator), abs(denominator)) # precondition assert ( isinstance(gcd_of_fraction, int) and (numerator % gcd_of_fraction == 0) and (denominator % gcd_of_fraction == 0) - ), "Error in function gcd(...,...)" + ), "Error in function gcd_by_iterative(...,...)" return (numerator // gcd_of_fraction, denominator // gcd_of_fraction) From 07d62b5e4bf3169aa0f0c66d799f4ba334a6cb59 Mon Sep 17 00:00:00 2001 From: Siddikpatel Date: Sun, 8 Oct 2023 10:29:30 +0530 Subject: [PATCH 08/11] more gcd duplicates removed --- ciphers/affine_cipher.py | 1 + ciphers/rsa_key_generator.py | 1 + maths/primelib.py | 1 + 3 files changed, 3 insertions(+) diff --git a/ciphers/affine_cipher.py b/ciphers/affine_cipher.py index 5010b13dd7aa..10d16367cced 100644 --- a/ciphers/affine_cipher.py +++ b/ciphers/affine_cipher.py @@ -1,5 +1,6 @@ import random import sys + from maths.greatest_common_divisor import gcd_by_iterative from . import cryptomath_module as cryptomath diff --git a/ciphers/rsa_key_generator.py b/ciphers/rsa_key_generator.py index ee35580f4d3d..44970e8cbc15 100644 --- a/ciphers/rsa_key_generator.py +++ b/ciphers/rsa_key_generator.py @@ -1,6 +1,7 @@ import os import random import sys + from maths.greatest_common_divisor import gcd_by_iterative from . import cryptomath_module, rabin_miller diff --git a/maths/primelib.py b/maths/primelib.py index b1edad1429ac..cf01750cf912 100644 --- a/maths/primelib.py +++ b/maths/primelib.py @@ -38,6 +38,7 @@ """ from math import sqrt + from maths.greatest_common_divisor import gcd_by_iterative From 70b6e06a3efd2b628eb315965d1de769b6389715 Mon Sep 17 00:00:00 2001 From: Tianyi Zheng Date: Sun, 8 Oct 2023 15:02:41 -0400 Subject: [PATCH 09/11] Update maths/carmichael_number.py --- maths/carmichael_number.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/maths/carmichael_number.py b/maths/carmichael_number.py index 4022c18490db..81712520ffc7 100644 --- a/maths/carmichael_number.py +++ b/maths/carmichael_number.py @@ -5,7 +5,7 @@ power(b, n-1) MOD n = 1, for all b ranging from 1 to n such that b and - n are relatively prime, i.e, greatest_common_divisor(b, n) = 1 + n are relatively prime, i.e, gcd(b, n) = 1 Examples of Carmichael Numbers: 561, 1105, ... https://en.wikipedia.org/wiki/Carmichael_number From 9a530aa0bd0c7001e777bfc3cd5261dd7cf61b72 Mon Sep 17 00:00:00 2001 From: Siddikpatel Date: Mon, 9 Oct 2023 07:42:50 +0530 Subject: [PATCH 10/11] updated files --- blockchain/modular_division.py | 1 - 1 file changed, 1 deletion(-) diff --git a/blockchain/modular_division.py b/blockchain/modular_division.py index 8e54bb67ca58..7915301ccab5 100644 --- a/blockchain/modular_division.py +++ b/blockchain/modular_division.py @@ -128,4 +128,3 @@ def extended_euclid(a: int, b: int) -> tuple[int, int]: 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 ce4753121abe2b074f84420a3d3bf66c78c79561 Mon Sep 17 00:00:00 2001 From: Siddikpatel Date: Mon, 9 Oct 2023 07:53:28 +0530 Subject: [PATCH 11/11] moved a file to another location --- blockchain/modular_division.py | 130 --------------------------------- 1 file changed, 130 deletions(-) delete mode 100644 blockchain/modular_division.py diff --git a/blockchain/modular_division.py b/blockchain/modular_division.py deleted file mode 100644 index 7915301ccab5..000000000000 --- a/blockchain/modular_division.py +++ /dev/null @@ -1,130 +0,0 @@ -from __future__ import annotations - -from maths.greatest_common_divisor import greatest_common_divisor - - -def modular_division(a: int, b: int, n: int) -> int: - """ - 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 - - >>> 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 - - -def invert_modulo(a: int, n: int) -> int: - """ - This function find the inverses of a i.e., a^(-1) - - >>> 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 ------------------- - - -def modular_division2(a: int, b: int, n: int) -> int: - """ - This function used the above inversion of a to find x = (b*a^(-1))mod 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 - - -def extended_gcd(a: int, b: int) -> tuple[int, int, int]: - """ - 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) - >>> 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) - - -def extended_euclid(a: int, b: int) -> tuple[int, int]: - """ - Extended Euclid - >>> 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) - - -if __name__ == "__main__": - from doctest import testmod - - 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)