Skip to content

Commit d890905

Browse files
fhlasekcclauss
authored andcommitted
More efficient least common multiple. (TheAlgorithms#2281)
* More efficient least common multiple. * lowest -> least * integer division * Update least_common_multiple.py Co-authored-by: Christian Clauss <[email protected]>
1 parent 8c13a35 commit d890905

File tree

1 file changed

+60
-9
lines changed

1 file changed

+60
-9
lines changed

Diff for: maths/least_common_multiple.py

+60-9
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,17 @@
11
import unittest
2+
from timeit import timeit
23

34

4-
def find_lcm(first_num: int, second_num: int) -> int:
5-
"""Find the least common multiple of two numbers.
5+
def least_common_multiple_slow(first_num: int, second_num: int) -> int:
6+
"""
7+
Find the least common multiple of two numbers.
68
7-
Learn more: https://en.wikipedia.org/wiki/Least_common_multiple
9+
Learn more: https://en.wikipedia.org/wiki/Least_common_multiple
810
9-
>>> find_lcm(5,2)
10-
10
11-
>>> find_lcm(12,76)
12-
228
11+
>>> least_common_multiple_slow(5, 2)
12+
10
13+
>>> least_common_multiple_slow(12, 76)
14+
228
1315
"""
1416
max_num = first_num if first_num >= second_num else second_num
1517
common_mult = max_num
@@ -18,6 +20,52 @@ def find_lcm(first_num: int, second_num: int) -> int:
1820
return common_mult
1921

2022

23+
def greatest_common_divisor(a: int, b: int) -> int:
24+
"""
25+
Calculate Greatest Common Divisor (GCD).
26+
see greatest_common_divisor.py
27+
>>> greatest_common_divisor(24, 40)
28+
8
29+
>>> greatest_common_divisor(1, 1)
30+
1
31+
>>> greatest_common_divisor(1, 800)
32+
1
33+
>>> greatest_common_divisor(11, 37)
34+
1
35+
>>> greatest_common_divisor(3, 5)
36+
1
37+
>>> greatest_common_divisor(16, 4)
38+
4
39+
"""
40+
return b if a == 0 else greatest_common_divisor(b % a, a)
41+
42+
43+
def least_common_multiple_fast(first_num: int, second_num: int) -> int:
44+
"""
45+
Find the least common multiple of two numbers.
46+
https://en.wikipedia.org/wiki/Least_common_multiple#Using_the_greatest_common_divisor
47+
>>> least_common_multiple_fast(5,2)
48+
10
49+
>>> least_common_multiple_fast(12,76)
50+
228
51+
"""
52+
return first_num // greatest_common_divisor(first_num, second_num) * second_num
53+
54+
55+
def benchmark():
56+
setup = (
57+
"from __main__ import least_common_multiple_slow, least_common_multiple_fast"
58+
)
59+
print(
60+
"least_common_multiple_slow():",
61+
timeit("least_common_multiple_slow(1000, 999)", setup=setup),
62+
)
63+
print(
64+
"least_common_multiple_fast():",
65+
timeit("least_common_multiple_fast(1000, 999)", setup=setup),
66+
)
67+
68+
2169
class TestLeastCommonMultiple(unittest.TestCase):
2270

2371
test_inputs = [
@@ -35,10 +83,13 @@ class TestLeastCommonMultiple(unittest.TestCase):
3583

3684
def test_lcm_function(self):
3785
for i, (first_num, second_num) in enumerate(self.test_inputs):
38-
actual_result = find_lcm(first_num, second_num)
86+
slow_result = least_common_multiple_slow(first_num, second_num)
87+
fast_result = least_common_multiple_fast(first_num, second_num)
3988
with self.subTest(i=i):
40-
self.assertEqual(actual_result, self.expected_results[i])
89+
self.assertEqual(slow_result, self.expected_results[i])
90+
self.assertEqual(fast_result, self.expected_results[i])
4191

4292

4393
if __name__ == "__main__":
94+
benchmark()
4495
unittest.main()

0 commit comments

Comments
 (0)