Skip to content

Commit 7fd75fc

Browse files
committed
Added doctests
1 parent 59bf2c6 commit 7fd75fc

File tree

2 files changed

+105
-53
lines changed

2 files changed

+105
-53
lines changed

divide_and_conquer/power.py

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,33 @@
1-
2-
3-
def power(a,b):
1+
def actual_power(a: int, b: int):
42
"""
53
Function using divide and conquer to calculate a^b.
64
It only works for integer a,b.
75
"""
86
if b == 0:
97
return 1
10-
elif ( (b%2) == 0 ):
11-
return (power(a,int(b/2)) * power(a,int(b/2)))
8+
if (b % 2) == 0:
9+
return actual_power(a, int(b / 2)) * actual_power(a, int(b / 2))
1210
else:
13-
return (a * power(a,int(b/2)) * power(a,int(b/2)))
11+
return a * actual_power(a, int(b / 2)) * actual_power(a, int(b / 2))
12+
13+
14+
def power(a: int, b: int) -> float:
15+
"""
16+
>>> power(4,6)
17+
4096
18+
>>> power(2,3)
19+
8
20+
>>> power(-2,3)
21+
-8
22+
>>> power(2,-3)
23+
0.125
24+
>>> power(-2,-3)
25+
-0.125
26+
"""
27+
if b < 0:
28+
return 1 / actual_power(a, b)
29+
return actual_power(a, b)
30+
1431

1532
if __name__ == "__main__":
16-
print(power(2,1000000))
33+
print(power(-2, -3))
Lines changed: 81 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,64 +1,87 @@
11
import math
2+
from typing import List, Tuple
23

3-
def default_matrix_multiplication(a, b):
4+
5+
def default_matrix_multiplication(a: List, b: List) -> List:
46
"""
57
Multiplication only for 2x2 matrices
68
"""
79
if len(a) != 2 or len(a[0]) != 2 or len(b) != 2 or len(b[0]) != 2:
8-
raise Exception('Matrices are not 2x2')
9-
new_matrix = [[a[0][0] * b[0][0] + a[0][1] * b[1][0], a[0][0] * b[0][1] + a[0][1] * b[1][1]],
10-
[a[1][0] * b[0][0] + a[1][1] * b[1][0], a[1][0] * b[0][1] + a[1][1] * b[1][1]]]
10+
raise Exception("Matrices are not 2x2")
11+
new_matrix = [
12+
[a[0][0] * b[0][0] + a[0][1] * b[1][0], a[0][0] * b[0][1] + a[0][1] * b[1][1]],
13+
[a[1][0] * b[0][0] + a[1][1] * b[1][0], a[1][0] * b[0][1] + a[1][1] * b[1][1]],
14+
]
1115
return new_matrix
1216

13-
def matrix_addition(matrix_a, matrix_b):
14-
return [[matrix_a[row][col] + matrix_b[row][col] for col in range(len(matrix_a[row]))] for row in range(len(matrix_a))]
1517

16-
def matrix_subtraction(matrix_a, matrix_b):
17-
return [[matrix_a[row][col] - matrix_b[row][col] for col in range(len(matrix_a[row]))] for row in range(len(matrix_a))]
18+
def matrix_addition(matrix_a: List, matrix_b: List):
19+
return [
20+
[matrix_a[row][col] + matrix_b[row][col] for col in range(len(matrix_a[row]))]
21+
for row in range(len(matrix_a))
22+
]
23+
24+
25+
def matrix_subtraction(matrix_a: List, matrix_b: List):
26+
return [
27+
[matrix_a[row][col] - matrix_b[row][col] for col in range(len(matrix_a[row]))]
28+
for row in range(len(matrix_a))
29+
]
1830

1931

20-
def split_matrix(a):
32+
def split_matrix(a: List,) -> Tuple[List, List, List, List]:
2133
"""
2234
Given an even length matrix, returns the top_left, top_right, bot_left, bot_right quadrant.
35+
36+
>>> split_matrix([[4,3,2,4],[2,3,1,1],[6,5,4,3],[8,4,1,6]])
37+
([[4, 3], [2, 3]], [[2, 4], [1, 1]], [[6, 5], [8, 4]], [[4, 3], [1, 6]])
38+
>>> split_matrix([[4,3,2,4,4,3,2,4],[2,3,1,1,2,3,1,1],[6,5,4,3,6,5,4,3],[8,4,1,6,8,4,1,6],[4,3,2,4,4,3,2,4],[2,3,1,1,2,3,1,1],[6,5,4,3,6,5,4,3],[8,4,1,6,8,4,1,6]])
39+
([[4, 3, 2, 4], [2, 3, 1, 1], [6, 5, 4, 3], [8, 4, 1, 6]], [[4, 3, 2, 4], [2, 3, 1, 1], [6, 5, 4, 3], [8, 4, 1, 6]], [[4, 3, 2, 4], [2, 3, 1, 1], [6, 5, 4, 3], [8, 4, 1, 6]], [[4, 3, 2, 4], [2, 3, 1, 1], [6, 5, 4, 3], [8, 4, 1, 6]])
2340
"""
2441
if len(a) % 2 != 0 or len(a[0]) % 2 != 0:
25-
raise Exception('Odd matrices are not supported!')
42+
raise Exception("Odd matrices are not supported!")
2643

2744
matrix_length = len(a)
2845
mid = matrix_length // 2
2946

3047
top_right = [[a[i][j] for j in range(mid, matrix_length)] for i in range(mid)]
31-
bot_right = [[a[i][j] for j in range(mid, matrix_length)] for i in range(mid, matrix_length)]
48+
bot_right = [
49+
[a[i][j] for j in range(mid, matrix_length)] for i in range(mid, matrix_length)
50+
]
3251

3352
top_left = [[a[i][j] for j in range(mid)] for i in range(mid)]
3453
bot_left = [[a[i][j] for j in range(mid)] for i in range(mid, matrix_length)]
3554

36-
37-
3855
return top_left, top_right, bot_left, bot_right
3956

40-
def matrix_dimensions(matrix):
57+
58+
def matrix_dimensions(matrix: List) -> Tuple[int, int]:
4159
return len(matrix), len(matrix[0])
4260

4361

44-
def strassen(matrix_a, matrix_b):
62+
def print_matrix(matrix: List) -> None:
63+
for i in range(len(matrix)):
64+
print(matrix[i])
65+
66+
67+
def actual_strassen(matrix_a: List, matrix_b: List) -> List:
4568
"""
4669
Recursive function to calculate the product of two matrices, using the Strassen Algorithm.
4770
It only supports even length matrices.
4871
"""
4972
if matrix_dimensions(matrix_a) == (2, 2):
5073
return default_matrix_multiplication(matrix_a, matrix_b)
5174

52-
a,b,c,d = split_matrix(matrix_a)
53-
e,f,g,h = split_matrix(matrix_b)
75+
a, b, c, d = split_matrix(matrix_a)
76+
e, f, g, h = split_matrix(matrix_b)
5477

55-
t1 = strassen(a, matrix_subtraction(f, h))
56-
t2 = strassen(matrix_addition(a, b), h)
57-
t3 = strassen(matrix_addition(c, d), e)
58-
t4 = strassen(d, matrix_subtraction(g, e))
59-
t5 = strassen(matrix_addition(a, d), matrix_addition(e, h))
60-
t6 = strassen(matrix_subtraction(b, d), matrix_addition(g, h))
61-
t7 = strassen(matrix_subtraction(a, c), matrix_addition(e, f))
78+
t1 = actual_strassen(a, matrix_subtraction(f, h))
79+
t2 = actual_strassen(matrix_addition(a, b), h)
80+
t3 = actual_strassen(matrix_addition(c, d), e)
81+
t4 = actual_strassen(d, matrix_subtraction(g, e))
82+
t5 = actual_strassen(matrix_addition(a, d), matrix_addition(e, h))
83+
t6 = actual_strassen(matrix_subtraction(b, d), matrix_addition(g, h))
84+
t7 = actual_strassen(matrix_subtraction(a, c), matrix_addition(e, f))
6285

6386
top_left = matrix_addition(matrix_subtraction(matrix_addition(t5, t4), t2), t6)
6487
top_right = matrix_addition(t1, t2)
@@ -73,13 +96,18 @@ def strassen(matrix_a, matrix_b):
7396
new_matrix.append(bot_left[i] + bot_right[i])
7497
return new_matrix
7598

76-
def print_matrix(matrix):
77-
for i in range(len(matrix)):
78-
print(matrix[i])
7999

80-
def multiply_matrices(matrix1, matrix2):
100+
def strassen(matrix1: List, matrix2: List) -> List:
101+
"""
102+
>>> strassen([[2,1,3],[3,4,6],[1,4,2],[7,6,7]], [[4,2,3,4],[2,1,1,1],[8,6,4,2]])
103+
[[34, 23, 19, 15], [68, 46, 37, 28], [28, 18, 15, 12], [96, 62, 55, 48]]
104+
>>> strassen([[3,7,5,6,9],[1,5,3,7,8],[1,4,4,5,7]], [[2,4],[5,2],[1,7],[5,5],[7,8]])
105+
[[139, 163], [121, 134], [100, 121]]
106+
"""
81107
if matrix_dimensions(matrix1)[1] != matrix_dimensions(matrix2)[0]:
82-
raise Exception(f'Unable to multiply these matrices, please check the dimensions. \nMatrix A:{matrix1} \nMatrix B:{matrix2}')
108+
raise Exception(
109+
f"Unable to multiply these matrices, please check the dimensions. \nMatrix A:{matrix1} \nMatrix B:{matrix2}"
110+
)
83111
dimension1 = matrix_dimensions(matrix1)
84112
dimension2 = matrix_dimensions(matrix2)
85113

@@ -88,39 +116,46 @@ def multiply_matrices(matrix1, matrix2):
88116

89117
maximum = max(max(dimension1), max(dimension2))
90118
maxim = int(math.pow(2, math.ceil(math.log2(maximum))))
91-
print(max)
92119
new_matrix1 = matrix1
93120
new_matrix2 = matrix2
94-
"""
95-
Adding zeros to the matrices so that the arrays dimensions are the same and also power of 2
96-
"""
97-
for i in range(0,maxim):
121+
122+
# Adding zeros to the matrices so that the arrays dimensions are the same and also power of 2
123+
for i in range(0, maxim):
98124
if i < dimension1[0]:
99-
for j in range(dimension1[1],maxim):
125+
for j in range(dimension1[1], maxim):
100126
new_matrix1[i].append(0)
101127
else:
102128
new_matrix1.append([0] * maxim)
103129
if i < dimension2[0]:
104-
for j in range(dimension2[1],maxim):
130+
for j in range(dimension2[1], maxim):
105131
new_matrix2[i].append(0)
106132
else:
107133
new_matrix2.append([0] * maxim)
108134

109-
final_matrix = strassen(new_matrix1, new_matrix2)
135+
final_matrix = actual_strassen(new_matrix1, new_matrix2)
110136

111-
"""
112-
Removing the additional zeros
113-
"""
114-
for i in range(0,maxim):
137+
# Removing the additional zeros
138+
for i in range(0, maxim):
115139
if i < dimension1[0]:
116-
for j in range(dimension2[1],maxim):
140+
for j in range(dimension2[1], maxim):
117141
final_matrix[i].pop()
118142
else:
119143
final_matrix.pop()
120144
return final_matrix
121145

122146

123-
if __name__ == '__main__':
124-
matrix1 = [[2,3,4,5],[6,4,3,1],[2,3,6,7],[3,1,2,4],[2,3,4,5],[6,4,3,1],[2,3,6,7],[3,1,2,4],[2,3,4,5],[6,2,3,1]]
125-
matrix2 = [[0,2,1,1],[16,2,3,3],[2,2,7,7],[13,11,22,4]]
126-
print_matrix(multiply_matrices(matrix1,matrix2))
147+
if __name__ == "__main__":
148+
matrix1= [
149+
[2, 3, 4, 5],
150+
[6, 4, 3, 1],
151+
[2, 3, 6, 7],
152+
[3, 1, 2, 4],
153+
[2, 3, 4, 5],
154+
[6, 4, 3, 1],
155+
[2, 3, 6, 7],
156+
[3, 1, 2, 4],
157+
[2, 3, 4, 5],
158+
[6, 2, 3, 1],
159+
]
160+
matrix2 = [[0, 2, 1, 1], [16, 2, 3, 3], [2, 2, 7, 7], [13, 11, 22, 4]]
161+
print(strassen(matrix1, matrix2))

0 commit comments

Comments
 (0)