More efficient least common multiple. (#2281)

* More efficient least common multiple.

* lowest -> least

* integer division

* Update least_common_multiple.py

Co-authored-by: Christian Clauss <cclauss@me.com>
This commit is contained in:
Filip Hlasek 2020-08-05 03:39:15 -07:00 committed by GitHub
parent a891f6802a
commit 871f8f4e00
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -1,14 +1,16 @@
import unittest import unittest
from timeit import timeit
def find_lcm(first_num: int, second_num: int) -> int: def least_common_multiple_slow(first_num: int, second_num: int) -> int:
"""Find the least common multiple of two numbers. """
Find the least common multiple of two numbers.
Learn more: https://en.wikipedia.org/wiki/Least_common_multiple Learn more: https://en.wikipedia.org/wiki/Least_common_multiple
>>> find_lcm(5,2) >>> least_common_multiple_slow(5, 2)
10 10
>>> find_lcm(12,76) >>> least_common_multiple_slow(12, 76)
228 228
""" """
max_num = first_num if first_num >= second_num else second_num max_num = first_num if first_num >= second_num else second_num
@ -18,6 +20,52 @@ def find_lcm(first_num: int, second_num: int) -> int:
return common_mult 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.
https://en.wikipedia.org/wiki/Least_common_multiple#Using_the_greatest_common_divisor
>>> least_common_multiple_fast(5,2)
10
>>> least_common_multiple_fast(12,76)
228
"""
return first_num // greatest_common_divisor(first_num, second_num) * second_num
def benchmark():
setup = (
"from __main__ import least_common_multiple_slow, least_common_multiple_fast"
)
print(
"least_common_multiple_slow():",
timeit("least_common_multiple_slow(1000, 999)", setup=setup),
)
print(
"least_common_multiple_fast():",
timeit("least_common_multiple_fast(1000, 999)", setup=setup),
)
class TestLeastCommonMultiple(unittest.TestCase): class TestLeastCommonMultiple(unittest.TestCase):
test_inputs = [ test_inputs = [
@ -35,10 +83,13 @@ class TestLeastCommonMultiple(unittest.TestCase):
def test_lcm_function(self): def test_lcm_function(self):
for i, (first_num, second_num) in enumerate(self.test_inputs): for i, (first_num, second_num) in enumerate(self.test_inputs):
actual_result = find_lcm(first_num, second_num) slow_result = least_common_multiple_slow(first_num, second_num)
fast_result = least_common_multiple_fast(first_num, second_num)
with self.subTest(i=i): with self.subTest(i=i):
self.assertEqual(actual_result, self.expected_results[i]) self.assertEqual(slow_result, self.expected_results[i])
self.assertEqual(fast_result, self.expected_results[i])
if __name__ == "__main__": if __name__ == "__main__":
benchmark()
unittest.main() unittest.main()