From fb1b939a89fb08370297cbb455846f61f66847bc Mon Sep 17 00:00:00 2001 From: Caeden Perelli-Harris Date: Mon, 14 Aug 2023 12:17:27 +0100 Subject: [PATCH] Consolidate find_min and find_min recursive and find_max and find_max_recursive (#8960) * updating DIRECTORY.md * refactor(min-max): Consolidate implementations * updating DIRECTORY.md * refactor(min-max): Append _iterative to func name --------- Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> --- DIRECTORY.md | 2 -- maths/find_max.py | 65 +++++++++++++++++++++++++++++++++---- maths/find_max_recursion.py | 58 --------------------------------- maths/find_min.py | 65 +++++++++++++++++++++++++++++++++---- maths/find_min_recursion.py | 58 --------------------------------- 5 files changed, 118 insertions(+), 130 deletions(-) delete mode 100644 maths/find_max_recursion.py delete mode 100644 maths/find_min_recursion.py diff --git a/DIRECTORY.md b/DIRECTORY.md index 384ce1b22..be5fa3584 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -573,9 +573,7 @@ * [Fermat Little Theorem](maths/fermat_little_theorem.py) * [Fibonacci](maths/fibonacci.py) * [Find Max](maths/find_max.py) - * [Find Max Recursion](maths/find_max_recursion.py) * [Find Min](maths/find_min.py) - * [Find Min Recursion](maths/find_min_recursion.py) * [Floor](maths/floor.py) * [Gamma](maths/gamma.py) * [Gamma Recursive](maths/gamma_recursive.py) diff --git a/maths/find_max.py b/maths/find_max.py index 684fbe816..729a80ab4 100644 --- a/maths/find_max.py +++ b/maths/find_max.py @@ -1,23 +1,23 @@ from __future__ import annotations -def find_max(nums: list[int | float]) -> int | float: +def find_max_iterative(nums: list[int | float]) -> int | float: """ >>> for nums in ([3, 2, 1], [-3, -2, -1], [3, -3, 0], [3.0, 3.1, 2.9]): - ... find_max(nums) == max(nums) + ... find_max_iterative(nums) == max(nums) True True True True - >>> find_max([2, 4, 9, 7, 19, 94, 5]) + >>> find_max_iterative([2, 4, 9, 7, 19, 94, 5]) 94 - >>> find_max([]) + >>> find_max_iterative([]) Traceback (most recent call last): ... - ValueError: find_max() arg is an empty sequence + ValueError: find_max_iterative() arg is an empty sequence """ if len(nums) == 0: - raise ValueError("find_max() arg is an empty sequence") + raise ValueError("find_max_iterative() arg is an empty sequence") max_num = nums[0] for x in nums: if x > max_num: @@ -25,6 +25,59 @@ def find_max(nums: list[int | float]) -> int | float: return max_num +# Divide and Conquer algorithm +def find_max_recursive(nums: list[int | float], left: int, right: int) -> int | float: + """ + find max value in list + :param nums: contains elements + :param left: index of first element + :param right: index of last element + :return: max in nums + + >>> for nums in ([3, 2, 1], [-3, -2, -1], [3, -3, 0], [3.0, 3.1, 2.9]): + ... find_max_recursive(nums, 0, len(nums) - 1) == max(nums) + True + True + True + True + >>> nums = [1, 3, 5, 7, 9, 2, 4, 6, 8, 10] + >>> find_max_recursive(nums, 0, len(nums) - 1) == max(nums) + True + >>> find_max_recursive([], 0, 0) + Traceback (most recent call last): + ... + ValueError: find_max_recursive() arg is an empty sequence + >>> find_max_recursive(nums, 0, len(nums)) == max(nums) + Traceback (most recent call last): + ... + IndexError: list index out of range + >>> find_max_recursive(nums, -len(nums), -1) == max(nums) + True + >>> find_max_recursive(nums, -len(nums) - 1, -1) == max(nums) + Traceback (most recent call last): + ... + IndexError: list index out of range + """ + if len(nums) == 0: + raise ValueError("find_max_recursive() arg is an empty sequence") + if ( + left >= len(nums) + or left < -len(nums) + or right >= len(nums) + or right < -len(nums) + ): + raise IndexError("list index out of range") + if left == right: + return nums[left] + mid = (left + right) >> 1 # the middle + left_max = find_max_recursive(nums, left, mid) # find max in range[left, mid] + right_max = find_max_recursive( + nums, mid + 1, right + ) # find max in range[mid + 1, right] + + return left_max if left_max >= right_max else right_max + + if __name__ == "__main__": import doctest diff --git a/maths/find_max_recursion.py b/maths/find_max_recursion.py deleted file mode 100644 index 629932e08..000000000 --- a/maths/find_max_recursion.py +++ /dev/null @@ -1,58 +0,0 @@ -from __future__ import annotations - - -# Divide and Conquer algorithm -def find_max(nums: list[int | float], left: int, right: int) -> int | float: - """ - find max value in list - :param nums: contains elements - :param left: index of first element - :param right: index of last element - :return: max in nums - - >>> for nums in ([3, 2, 1], [-3, -2, -1], [3, -3, 0], [3.0, 3.1, 2.9]): - ... find_max(nums, 0, len(nums) - 1) == max(nums) - True - True - True - True - >>> nums = [1, 3, 5, 7, 9, 2, 4, 6, 8, 10] - >>> find_max(nums, 0, len(nums) - 1) == max(nums) - True - >>> find_max([], 0, 0) - Traceback (most recent call last): - ... - ValueError: find_max() arg is an empty sequence - >>> find_max(nums, 0, len(nums)) == max(nums) - Traceback (most recent call last): - ... - IndexError: list index out of range - >>> find_max(nums, -len(nums), -1) == max(nums) - True - >>> find_max(nums, -len(nums) - 1, -1) == max(nums) - Traceback (most recent call last): - ... - IndexError: list index out of range - """ - if len(nums) == 0: - raise ValueError("find_max() arg is an empty sequence") - if ( - left >= len(nums) - or left < -len(nums) - or right >= len(nums) - or right < -len(nums) - ): - raise IndexError("list index out of range") - if left == right: - return nums[left] - mid = (left + right) >> 1 # the middle - left_max = find_max(nums, left, mid) # find max in range[left, mid] - right_max = find_max(nums, mid + 1, right) # find max in range[mid + 1, right] - - return left_max if left_max >= right_max else right_max - - -if __name__ == "__main__": - import doctest - - doctest.testmod(verbose=True) diff --git a/maths/find_min.py b/maths/find_min.py index 2eac087c6..762562e36 100644 --- a/maths/find_min.py +++ b/maths/find_min.py @@ -1,33 +1,86 @@ from __future__ import annotations -def find_min(nums: list[int | float]) -> int | float: +def find_min_iterative(nums: list[int | float]) -> int | float: """ Find Minimum Number in a List :param nums: contains elements :return: min number in list >>> for nums in ([3, 2, 1], [-3, -2, -1], [3, -3, 0], [3.0, 3.1, 2.9]): - ... find_min(nums) == min(nums) + ... find_min_iterative(nums) == min(nums) True True True True - >>> find_min([0, 1, 2, 3, 4, 5, -3, 24, -56]) + >>> find_min_iterative([0, 1, 2, 3, 4, 5, -3, 24, -56]) -56 - >>> find_min([]) + >>> find_min_iterative([]) Traceback (most recent call last): ... - ValueError: find_min() arg is an empty sequence + ValueError: find_min_iterative() arg is an empty sequence """ if len(nums) == 0: - raise ValueError("find_min() arg is an empty sequence") + raise ValueError("find_min_iterative() arg is an empty sequence") min_num = nums[0] for num in nums: min_num = min(min_num, num) return min_num +# Divide and Conquer algorithm +def find_min_recursive(nums: list[int | float], left: int, right: int) -> int | float: + """ + find min value in list + :param nums: contains elements + :param left: index of first element + :param right: index of last element + :return: min in nums + + >>> for nums in ([3, 2, 1], [-3, -2, -1], [3, -3, 0], [3.0, 3.1, 2.9]): + ... find_min_recursive(nums, 0, len(nums) - 1) == min(nums) + True + True + True + True + >>> nums = [1, 3, 5, 7, 9, 2, 4, 6, 8, 10] + >>> find_min_recursive(nums, 0, len(nums) - 1) == min(nums) + True + >>> find_min_recursive([], 0, 0) + Traceback (most recent call last): + ... + ValueError: find_min_recursive() arg is an empty sequence + >>> find_min_recursive(nums, 0, len(nums)) == min(nums) + Traceback (most recent call last): + ... + IndexError: list index out of range + >>> find_min_recursive(nums, -len(nums), -1) == min(nums) + True + >>> find_min_recursive(nums, -len(nums) - 1, -1) == min(nums) + Traceback (most recent call last): + ... + IndexError: list index out of range + """ + if len(nums) == 0: + raise ValueError("find_min_recursive() arg is an empty sequence") + if ( + left >= len(nums) + or left < -len(nums) + or right >= len(nums) + or right < -len(nums) + ): + raise IndexError("list index out of range") + if left == right: + return nums[left] + mid = (left + right) >> 1 # the middle + left_min = find_min_recursive(nums, left, mid) # find min in range[left, mid] + right_min = find_min_recursive( + nums, mid + 1, right + ) # find min in range[mid + 1, right] + + return left_min if left_min <= right_min else right_min + + if __name__ == "__main__": import doctest diff --git a/maths/find_min_recursion.py b/maths/find_min_recursion.py deleted file mode 100644 index 4d11015ef..000000000 --- a/maths/find_min_recursion.py +++ /dev/null @@ -1,58 +0,0 @@ -from __future__ import annotations - - -# Divide and Conquer algorithm -def find_min(nums: list[int | float], left: int, right: int) -> int | float: - """ - find min value in list - :param nums: contains elements - :param left: index of first element - :param right: index of last element - :return: min in nums - - >>> for nums in ([3, 2, 1], [-3, -2, -1], [3, -3, 0], [3.0, 3.1, 2.9]): - ... find_min(nums, 0, len(nums) - 1) == min(nums) - True - True - True - True - >>> nums = [1, 3, 5, 7, 9, 2, 4, 6, 8, 10] - >>> find_min(nums, 0, len(nums) - 1) == min(nums) - True - >>> find_min([], 0, 0) - Traceback (most recent call last): - ... - ValueError: find_min() arg is an empty sequence - >>> find_min(nums, 0, len(nums)) == min(nums) - Traceback (most recent call last): - ... - IndexError: list index out of range - >>> find_min(nums, -len(nums), -1) == min(nums) - True - >>> find_min(nums, -len(nums) - 1, -1) == min(nums) - Traceback (most recent call last): - ... - IndexError: list index out of range - """ - if len(nums) == 0: - raise ValueError("find_min() arg is an empty sequence") - if ( - left >= len(nums) - or left < -len(nums) - or right >= len(nums) - or right < -len(nums) - ): - raise IndexError("list index out of range") - if left == right: - return nums[left] - mid = (left + right) >> 1 # the middle - left_min = find_min(nums, left, mid) # find min in range[left, mid] - right_min = find_min(nums, mid + 1, right) # find min in range[mid + 1, right] - - return left_min if left_min <= right_min else right_min - - -if __name__ == "__main__": - import doctest - - doctest.testmod(verbose=True)