From bde12dd1337b063bbc5491ee0e0cd530495add13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Hl=C3=A1sek?= Date: Wed, 5 Aug 2020 01:03:41 -0700 Subject: [PATCH 1/4] More efficient least common multiple. --- maths/least_common_multiple.py | 69 +++++++++++++++++++++++++++++----- 1 file changed, 60 insertions(+), 9 deletions(-) diff --git a/maths/least_common_multiple.py b/maths/least_common_multiple.py index 863744e182b6..3991aded4dca 100644 --- a/maths/least_common_multiple.py +++ b/maths/least_common_multiple.py @@ -1,15 +1,17 @@ import unittest +from timeit import timeit -def find_lcm(first_num: int, second_num: int) -> int: - """Find the least common multiple of two numbers. +def lowest_common_multiple_slow(first_num: int, second_num: int) -> int: + """ + 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) - 10 - >>> find_lcm(12,76) - 228 + >>> lowest_common_multiple_slow(5,2) + 10 + >>> lowest_common_multiple_slow(12,76) + 228 """ max_num = first_num if first_num >= second_num else second_num common_mult = max_num @@ -18,6 +20,52 @@ def find_lcm(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 lowest_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 + >>> lowest_common_multiple_fast(5,2) + 10 + >>> lowest_common_multiple_fast(12,76) + 228 + """ + return first_num / greatest_common_divisor(first_num, second_num) * second_num + + +def benchmark(): + setup = ( + "from __main__ import lowest_common_multiple_slow, lowest_common_multiple_fast" + ) + print( + "lowest_common_multiple_slow():", + timeit("lowest_common_multiple_slow(1000, 999)", setup=setup), + ) + print( + "lowest_common_multiple_fast():", + timeit("lowest_common_multiple_fast(1000, 999)", setup=setup), + ) + + class TestLeastCommonMultiple(unittest.TestCase): test_inputs = [ @@ -35,10 +83,13 @@ class TestLeastCommonMultiple(unittest.TestCase): def test_lcm_function(self): for i, (first_num, second_num) in enumerate(self.test_inputs): - actual_result = find_lcm(first_num, second_num) + slow_result = lowest_common_multiple_slow(first_num, second_num) + fast_result = lowest_common_multiple_fast(first_num, second_num) 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__": + benchmark() unittest.main() From f1669ed0d80b9ebf78dcc5ee302cd34eddaa4b04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Hl=C3=A1sek?= Date: Wed, 5 Aug 2020 01:06:39 -0700 Subject: [PATCH 2/4] lowest -> least --- maths/least_common_multiple.py | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/maths/least_common_multiple.py b/maths/least_common_multiple.py index 3991aded4dca..8a566778ae8d 100644 --- a/maths/least_common_multiple.py +++ b/maths/least_common_multiple.py @@ -2,15 +2,15 @@ from timeit import timeit -def lowest_common_multiple_slow(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. Learn more: https://en.wikipedia.org/wiki/Least_common_multiple - >>> lowest_common_multiple_slow(5,2) + >>> least_common_multiple_slow(5,2) 10 - >>> lowest_common_multiple_slow(12,76) + >>> least_common_multiple_slow(12,76) 228 """ max_num = first_num if first_num >= second_num else second_num @@ -40,13 +40,13 @@ def greatest_common_divisor(a: int, b: int) -> int: return b if a == 0 else greatest_common_divisor(b % a, a) -def lowest_common_multiple_fast(first_num: int, second_num: int) -> int: +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 - >>> lowest_common_multiple_fast(5,2) + >>> least_common_multiple_fast(5,2) 10 - >>> lowest_common_multiple_fast(12,76) + >>> least_common_multiple_fast(12,76) 228 """ return first_num / greatest_common_divisor(first_num, second_num) * second_num @@ -54,15 +54,15 @@ def lowest_common_multiple_fast(first_num: int, second_num: int) -> int: def benchmark(): setup = ( - "from __main__ import lowest_common_multiple_slow, lowest_common_multiple_fast" + "from __main__ import least_common_multiple_slow, least_common_multiple_fast" ) print( - "lowest_common_multiple_slow():", - timeit("lowest_common_multiple_slow(1000, 999)", setup=setup), + "least_common_multiple_slow():", + timeit("least_common_multiple_slow(1000, 999)", setup=setup), ) print( - "lowest_common_multiple_fast():", - timeit("lowest_common_multiple_fast(1000, 999)", setup=setup), + "least_common_multiple_fast():", + timeit("least_common_multiple_fast(1000, 999)", setup=setup), ) @@ -83,8 +83,8 @@ class TestLeastCommonMultiple(unittest.TestCase): def test_lcm_function(self): for i, (first_num, second_num) in enumerate(self.test_inputs): - slow_result = lowest_common_multiple_slow(first_num, second_num) - fast_result = lowest_common_multiple_fast(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): self.assertEqual(slow_result, self.expected_results[i]) self.assertEqual(fast_result, self.expected_results[i]) From 6273051f40be1768e77c6f8b01f2bec5dcd1c711 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Hl=C3=A1sek?= Date: Wed, 5 Aug 2020 01:25:24 -0700 Subject: [PATCH 3/4] integer division --- maths/least_common_multiple.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/maths/least_common_multiple.py b/maths/least_common_multiple.py index 8a566778ae8d..6a88346a88c3 100644 --- a/maths/least_common_multiple.py +++ b/maths/least_common_multiple.py @@ -49,7 +49,7 @@ def least_common_multiple_fast(first_num: int, second_num: int) -> int: >>> least_common_multiple_fast(12,76) 228 """ - return first_num / greatest_common_divisor(first_num, second_num) * second_num + return first_num // greatest_common_divisor(first_num, second_num) * second_num def benchmark(): From cdce81a48c600a5a10088e41590b0faaab401e17 Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Wed, 5 Aug 2020 12:38:40 +0200 Subject: [PATCH 4/4] Update least_common_multiple.py --- maths/least_common_multiple.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/maths/least_common_multiple.py b/maths/least_common_multiple.py index 6a88346a88c3..0d087643e869 100644 --- a/maths/least_common_multiple.py +++ b/maths/least_common_multiple.py @@ -8,9 +8,9 @@ def least_common_multiple_slow(first_num: int, second_num: int) -> int: Learn more: https://en.wikipedia.org/wiki/Least_common_multiple - >>> least_common_multiple_slow(5,2) + >>> least_common_multiple_slow(5, 2) 10 - >>> least_common_multiple_slow(12,76) + >>> least_common_multiple_slow(12, 76) 228 """ max_num = first_num if first_num >= second_num else second_num