forked from keon/algorithms
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathgcd.py
More file actions
113 lines (86 loc) · 2.29 KB
/
gcd.py
File metadata and controls
113 lines (86 loc) · 2.29 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
"""
Greatest Common Divisor and Least Common Multiple
Compute the GCD and LCM of two integers using Euclid's algorithm and
a bitwise variant.
Reference: https://en.wikipedia.org/wiki/Euclidean_algorithm
Complexity:
Time: O(log(min(a, b))) for gcd, O(log(min(a, b))) for lcm
Space: O(1)
"""
from __future__ import annotations
def gcd(a: int, b: int) -> int:
"""Compute the greatest common divisor using Euclid's algorithm.
Args:
a: First integer (non-zero).
b: Second integer (non-zero).
Returns:
The greatest common divisor of a and b.
Raises:
ValueError: If inputs are not integers or either is zero.
Examples:
>>> gcd(8, 12)
4
>>> gcd(13, 17)
1
"""
a_int = isinstance(a, int)
b_int = isinstance(b, int)
a = abs(a)
b = abs(b)
if not (a_int or b_int):
raise ValueError("Input arguments are not integers")
if (a == 0) or (b == 0):
raise ValueError("One or more input arguments equals zero")
while b != 0:
a, b = b, a % b
return a
def lcm(a: int, b: int) -> int:
"""Compute the lowest common multiple of two integers.
Args:
a: First integer (non-zero).
b: Second integer (non-zero).
Returns:
The lowest common multiple of a and b.
Examples:
>>> lcm(8, 12)
24
"""
return abs(a) * abs(b) / gcd(a, b)
def trailing_zero(x: int) -> int:
"""Count the number of trailing zeros in the binary representation.
Args:
x: A positive integer.
Returns:
Number of trailing zero bits.
Examples:
>>> trailing_zero(34)
1
>>> trailing_zero(40)
3
"""
count = 0
while x and not x & 1:
count += 1
x >>= 1
return count
def gcd_bit(a: int, b: int) -> int:
"""Compute GCD using the binary (Stein's) algorithm.
Args:
a: First non-negative integer.
b: Second non-negative integer.
Returns:
The greatest common divisor of a and b.
Examples:
>>> gcd_bit(8, 12)
4
"""
tza = trailing_zero(a)
tzb = trailing_zero(b)
a >>= tza
b >>= tzb
while b:
if a < b:
a, b = b, a
a -= b
a >>= trailing_zero(a)
return a << min(tza, tzb)