Skip to content

Commit 0b8f54a

Browse files
committed
feat: Concatenate algorithm implementations
1 parent b7e876a commit 0b8f54a

File tree

6 files changed

+176
-195
lines changed

6 files changed

+176
-195
lines changed

maths/find_max.py

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,57 @@ def find_max(nums: list[int | float]) -> int | float:
2525
return max_num
2626

2727

28+
# Divide and Conquer algorithm
29+
def find_max_recursive(nums: list[int | float], left: int, right: int) -> int | float:
30+
"""
31+
find max value in list
32+
:param nums: contains elements
33+
:param left: index of first element
34+
:param right: index of last element
35+
:return: max in nums
36+
37+
>>> for nums in ([3, 2, 1], [-3, -2, -1], [3, -3, 0], [3.0, 3.1, 2.9]):
38+
... find_max(nums, 0, len(nums) - 1) == max(nums)
39+
True
40+
True
41+
True
42+
True
43+
>>> nums = [1, 3, 5, 7, 9, 2, 4, 6, 8, 10]
44+
>>> find_max(nums, 0, len(nums) - 1) == max(nums)
45+
True
46+
>>> find_max([], 0, 0)
47+
Traceback (most recent call last):
48+
...
49+
ValueError: find_max() arg is an empty sequence
50+
>>> find_max(nums, 0, len(nums)) == max(nums)
51+
Traceback (most recent call last):
52+
...
53+
IndexError: list index out of range
54+
>>> find_max(nums, -len(nums), -1) == max(nums)
55+
True
56+
>>> find_max(nums, -len(nums) - 1, -1) == max(nums)
57+
Traceback (most recent call last):
58+
...
59+
IndexError: list index out of range
60+
"""
61+
if len(nums) == 0:
62+
raise ValueError("find_max() arg is an empty sequence")
63+
if (
64+
left >= len(nums)
65+
or left < -len(nums)
66+
or right >= len(nums)
67+
or right < -len(nums)
68+
):
69+
raise IndexError("list index out of range")
70+
if left == right:
71+
return nums[left]
72+
mid = (left + right) >> 1 # the middle
73+
left_max = find_max(nums, left, mid) # find max in range[left, mid]
74+
right_max = find_max(nums, mid + 1, right) # find max in range[mid + 1, right]
75+
76+
return left_max if left_max >= right_max else right_max
77+
78+
2879
if __name__ == "__main__":
2980
import doctest
3081

maths/find_max_recursion.py

Lines changed: 0 additions & 58 deletions
This file was deleted.

maths/find_min.py

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,57 @@ def find_min(nums: list[int | float]) -> int | float:
2828
return min_num
2929

3030

31+
# Divide and Conquer algorithm
32+
def find_min(nums: list[int | float], left: int, right: int) -> int | float:
33+
"""
34+
find min value in list
35+
:param nums: contains elements
36+
:param left: index of first element
37+
:param right: index of last element
38+
:return: min in nums
39+
40+
>>> for nums in ([3, 2, 1], [-3, -2, -1], [3, -3, 0], [3.0, 3.1, 2.9]):
41+
... find_min(nums, 0, len(nums) - 1) == min(nums)
42+
True
43+
True
44+
True
45+
True
46+
>>> nums = [1, 3, 5, 7, 9, 2, 4, 6, 8, 10]
47+
>>> find_min(nums, 0, len(nums) - 1) == min(nums)
48+
True
49+
>>> find_min([], 0, 0)
50+
Traceback (most recent call last):
51+
...
52+
ValueError: find_min() arg is an empty sequence
53+
>>> find_min(nums, 0, len(nums)) == min(nums)
54+
Traceback (most recent call last):
55+
...
56+
IndexError: list index out of range
57+
>>> find_min(nums, -len(nums), -1) == min(nums)
58+
True
59+
>>> find_min(nums, -len(nums) - 1, -1) == min(nums)
60+
Traceback (most recent call last):
61+
...
62+
IndexError: list index out of range
63+
"""
64+
if len(nums) == 0:
65+
raise ValueError("find_min() arg is an empty sequence")
66+
if (
67+
left >= len(nums)
68+
or left < -len(nums)
69+
or right >= len(nums)
70+
or right < -len(nums)
71+
):
72+
raise IndexError("list index out of range")
73+
if left == right:
74+
return nums[left]
75+
mid = (left + right) >> 1 # the middle
76+
left_min = find_min(nums, left, mid) # find min in range[left, mid]
77+
right_min = find_min(nums, mid + 1, right) # find min in range[mid + 1, right]
78+
79+
return left_min if left_min <= right_min else right_min
80+
81+
3182
if __name__ == "__main__":
3283
import doctest
3384

maths/find_min_recursion.py

Lines changed: 0 additions & 58 deletions
This file was deleted.

maths/gamma.py

Lines changed: 74 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,11 @@
1-
import math
1+
"""
2+
Gamma function is a very useful tool in math and physics.
3+
It helps calculating complex integral in a convenient way.
4+
for more info: https://en.wikipedia.org/wiki/Gamma_function
5+
Python's Standard Library gamma() function overflows around gamma(171.624).
6+
"""
7+
8+
from math import pi, sqrt, exp
29

310
from numpy import inf
411
from scipy.integrate import quad
@@ -39,10 +46,75 @@ def gamma(num: float) -> float:
3946

4047

4148
def integrand(x: float, z: float) -> float:
42-
return math.pow(x, z - 1) * math.exp(-x)
49+
return pow(x, z - 1) * exp(-x)
50+
51+
52+
def gamma_recursive(num: float) -> float:
53+
"""
54+
Calculates the value of Gamma function of num
55+
where num is either an integer (1, 2, 3..) or a half-integer (0.5, 1.5, 2.5 ...).
56+
Implemented using recursion
57+
Examples:
58+
>>> from math import isclose, gamma as math_gamma
59+
>>> gamma(0.5)
60+
1.7724538509055159
61+
>>> gamma(2)
62+
1.0
63+
>>> gamma(3.5)
64+
3.3233509704478426
65+
>>> gamma(171.5)
66+
9.483367566824795e+307
67+
>>> all(isclose(gamma(num), math_gamma(num)) for num in (0.5, 2, 3.5, 171.5))
68+
True
69+
>>> gamma(0)
70+
Traceback (most recent call last):
71+
...
72+
ValueError: math domain error
73+
>>> gamma(-1.1)
74+
Traceback (most recent call last):
75+
...
76+
ValueError: math domain error
77+
>>> gamma(-4)
78+
Traceback (most recent call last):
79+
...
80+
ValueError: math domain error
81+
>>> gamma(172)
82+
Traceback (most recent call last):
83+
...
84+
OverflowError: math range error
85+
>>> gamma(1.1)
86+
Traceback (most recent call last):
87+
...
88+
NotImplementedError: num must be an integer or a half-integer
89+
"""
90+
if num <= 0:
91+
raise ValueError("math domain error")
92+
if num > 171.5:
93+
raise OverflowError("math range error")
94+
elif num - int(num) not in (0, 0.5):
95+
raise NotImplementedError("num must be an integer or a half-integer")
96+
elif num == 0.5:
97+
return sqrt(pi)
98+
else:
99+
return 1.0 if num == 1 else (num - 1) * gamma(num - 1)
100+
43101

102+
def test_gamma() -> None:
103+
"""
104+
>>> test_gamma()
105+
"""
106+
assert gamma(0.5) == sqrt(pi)
107+
assert gamma(1) == 1.0
108+
assert gamma(2) == 1.0
109+
44110

45111
if __name__ == "__main__":
46112
from doctest import testmod
47113

48114
testmod()
115+
116+
num = 1.0
117+
while num:
118+
num = float(input("Gamma of: "))
119+
print(f"gamma({num}) = {gamma(num)}")
120+
print("\nEnter 0 to exit...")

0 commit comments

Comments
 (0)