Skip to content

Commit 77b243e

Browse files
authored
bugfix: Add empty list detection for find_max/min (#4881)
* bugfix: Add empty list detection for find_max/min * fix shebangs check
1 parent d324f91 commit 77b243e

File tree

4 files changed

+100
-19
lines changed

4 files changed

+100
-19
lines changed

maths/find_max.py

+13-7
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,31 @@
1-
# NguyenU
1+
from __future__ import annotations
22

33

4-
def find_max(nums):
4+
def find_max(nums: list[int | float]) -> int | float:
55
"""
66
>>> for nums in ([3, 2, 1], [-3, -2, -1], [3, -3, 0], [3.0, 3.1, 2.9]):
77
... find_max(nums) == max(nums)
88
True
99
True
1010
True
1111
True
12+
>>> find_max([2, 4, 9, 7, 19, 94, 5])
13+
94
14+
>>> find_max([])
15+
Traceback (most recent call last):
16+
...
17+
ValueError: find_max() arg is an empty sequence
1218
"""
19+
if len(nums) == 0:
20+
raise ValueError("find_max() arg is an empty sequence")
1321
max_num = nums[0]
1422
for x in nums:
1523
if x > max_num:
1624
max_num = x
1725
return max_num
1826

1927

20-
def main():
21-
print(find_max([2, 4, 9, 7, 19, 94, 5])) # 94
22-
23-
2428
if __name__ == "__main__":
25-
main()
29+
import doctest
30+
31+
doctest.testmod(verbose=True)

maths/find_max_recursion.py

+36-3
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,48 @@
1+
from __future__ import annotations
2+
3+
14
# Divide and Conquer algorithm
2-
def find_max(nums, left, right):
5+
def find_max(nums: list[int | float], left: int, right: int) -> int | float:
36
"""
47
find max value in list
58
:param nums: contains elements
69
:param left: index of first element
710
:param right: index of last element
811
:return: max in nums
912
13+
>>> for nums in ([3, 2, 1], [-3, -2, -1], [3, -3, 0], [3.0, 3.1, 2.9]):
14+
... find_max(nums, 0, len(nums) - 1) == max(nums)
15+
True
16+
True
17+
True
18+
True
1019
>>> nums = [1, 3, 5, 7, 9, 2, 4, 6, 8, 10]
1120
>>> find_max(nums, 0, len(nums) - 1) == max(nums)
1221
True
22+
>>> find_max([], 0, 0)
23+
Traceback (most recent call last):
24+
...
25+
ValueError: find_max() arg is an empty sequence
26+
>>> find_max(nums, 0, len(nums)) == max(nums)
27+
Traceback (most recent call last):
28+
...
29+
IndexError: list index out of range
30+
>>> find_max(nums, -len(nums), -1) == max(nums)
31+
True
32+
>>> find_max(nums, -len(nums) - 1, -1) == max(nums)
33+
Traceback (most recent call last):
34+
...
35+
IndexError: list index out of range
1336
"""
37+
if len(nums) == 0:
38+
raise ValueError("find_max() arg is an empty sequence")
39+
if (
40+
left >= len(nums)
41+
or left < -len(nums)
42+
or right >= len(nums)
43+
or right < -len(nums)
44+
):
45+
raise IndexError("list index out of range")
1446
if left == right:
1547
return nums[left]
1648
mid = (left + right) >> 1 # the middle
@@ -21,5 +53,6 @@ def find_max(nums, left, right):
2153

2254

2355
if __name__ == "__main__":
24-
nums = [1, 3, 5, 7, 9, 2, 4, 6, 8, 10]
25-
assert find_max(nums, 0, len(nums) - 1) == 10
56+
import doctest
57+
58+
doctest.testmod(verbose=True)

maths/find_min.py

+15-6
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
def find_min(nums):
1+
from __future__ import annotations
2+
3+
4+
def find_min(nums: list[int | float]) -> int | float:
25
"""
36
Find Minimum Number in a List
47
:param nums: contains elements
@@ -10,17 +13,23 @@ def find_min(nums):
1013
True
1114
True
1215
True
16+
>>> find_min([0, 1, 2, 3, 4, 5, -3, 24, -56])
17+
-56
18+
>>> find_min([])
19+
Traceback (most recent call last):
20+
...
21+
ValueError: find_min() arg is an empty sequence
1322
"""
23+
if len(nums) == 0:
24+
raise ValueError("find_min() arg is an empty sequence")
1425
min_num = nums[0]
1526
for num in nums:
1627
if min_num > num:
1728
min_num = num
1829
return min_num
1930

2031

21-
def main():
22-
assert find_min([0, 1, 2, 3, 4, 5, -3, 24, -56]) == -56
23-
24-
2532
if __name__ == "__main__":
26-
main()
33+
import doctest
34+
35+
doctest.testmod(verbose=True)

maths/find_min_recursion.py

+36-3
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,48 @@
1+
from __future__ import annotations
2+
3+
14
# Divide and Conquer algorithm
2-
def find_min(nums, left, right):
5+
def find_min(nums: list[int | float], left: int, right: int) -> int | float:
36
"""
47
find min value in list
58
:param nums: contains elements
69
:param left: index of first element
710
:param right: index of last element
811
:return: min in nums
912
13+
>>> for nums in ([3, 2, 1], [-3, -2, -1], [3, -3, 0], [3.0, 3.1, 2.9]):
14+
... find_min(nums, 0, len(nums) - 1) == min(nums)
15+
True
16+
True
17+
True
18+
True
1019
>>> nums = [1, 3, 5, 7, 9, 2, 4, 6, 8, 10]
1120
>>> find_min(nums, 0, len(nums) - 1) == min(nums)
1221
True
22+
>>> find_min([], 0, 0)
23+
Traceback (most recent call last):
24+
...
25+
ValueError: find_min() arg is an empty sequence
26+
>>> find_min(nums, 0, len(nums)) == min(nums)
27+
Traceback (most recent call last):
28+
...
29+
IndexError: list index out of range
30+
>>> find_min(nums, -len(nums), -1) == min(nums)
31+
True
32+
>>> find_min(nums, -len(nums) - 1, -1) == min(nums)
33+
Traceback (most recent call last):
34+
...
35+
IndexError: list index out of range
1336
"""
37+
if len(nums) == 0:
38+
raise ValueError("find_min() arg is an empty sequence")
39+
if (
40+
left >= len(nums)
41+
or left < -len(nums)
42+
or right >= len(nums)
43+
or right < -len(nums)
44+
):
45+
raise IndexError("list index out of range")
1446
if left == right:
1547
return nums[left]
1648
mid = (left + right) >> 1 # the middle
@@ -21,5 +53,6 @@ def find_min(nums, left, right):
2153

2254

2355
if __name__ == "__main__":
24-
nums = [1, 3, 5, 7, 9, 2, 4, 6, 8, 10]
25-
assert find_min(nums, 0, len(nums) - 1) == 1
56+
import doctest
57+
58+
doctest.testmod(verbose=True)

0 commit comments

Comments
 (0)