1
1
"""
2
- This implementation demonstrates how to generate the
3
- elements of a Pascal's triangle. The element having
4
- a row index of r and column index of c can be derived
5
- as follows:
2
+ This implementation demonstrates how to generate the elements of a Pascal's triangle.
3
+ The element havingva row index of r and column index of c can be derivedvas follows:
6
4
triangle[r][c] = triangle[r-1][c-1]+triangle[r-1][c]
7
- What is Pascal's triangle?
8
- - It is a triangular array containing binomial coefficients.
9
- Refer to (https://en.wikipedia.org/wiki/Pascal%27s_triangle)
10
- for more info about this triangle.
5
+
6
+ A Pascal's triangle is a triangular array containing binomial coefficients.
7
+ https://en.wikipedia.org/wiki/Pascal%27s_triangle
11
8
"""
12
9
13
10
@@ -38,6 +35,8 @@ def print_pascal_triangle(num_rows: int) -> None:
38
35
def generate_pascal_triangle (num_rows : int ) -> list [list [int ]]:
39
36
"""
40
37
Create Pascal's triangle for different number of rows
38
+ >>> generate_pascal_triangle(0)
39
+ []
41
40
>>> generate_pascal_triangle(1)
42
41
[[1]]
43
42
>>> generate_pascal_triangle(2)
@@ -48,7 +47,26 @@ def generate_pascal_triangle(num_rows: int) -> list[list[int]]:
48
47
[[1], [1, 1], [1, 2, 1], [1, 3, 3, 1]]
49
48
>>> generate_pascal_triangle(5)
50
49
[[1], [1, 1], [1, 2, 1], [1, 3, 3, 1], [1, 4, 6, 4, 1]]
50
+ >>> generate_pascal_triangle(-5)
51
+ Traceback (most recent call last):
52
+ ...
53
+ ValueError: The input value of 'num_rows' should be greater than or equal to 0
54
+ >>> generate_pascal_triangle(7.89)
55
+ Traceback (most recent call last):
56
+ ...
57
+ TypeError: The input value of 'num_rows' should be 'int'
51
58
"""
59
+
60
+ if not isinstance (num_rows , int ):
61
+ raise TypeError ("The input value of 'num_rows' should be 'int'" )
62
+
63
+ if num_rows == 0 :
64
+ return []
65
+ elif num_rows < 0 :
66
+ raise ValueError (
67
+ "The input value of 'num_rows' should be greater than or equal to 0"
68
+ )
69
+
52
70
triangle : list [list [int ]] = []
53
71
for current_row_idx in range (num_rows ):
54
72
current_row = populate_current_row (triangle , current_row_idx )
@@ -90,7 +108,82 @@ def calculate_current_element(
90
108
current_row [current_col_idx ] = above_to_left_elt + above_to_right_elt
91
109
92
110
111
+ def generate_pascal_triangle_optimized (num_rows : int ) -> list [list [int ]]:
112
+ """
113
+ This function returns a matrix representing the corresponding pascal's triangle
114
+ according to the given input of number of rows of Pascal's triangle to be generated.
115
+ It reduces the operations done to generate a row by half
116
+ by eliminating redundant calculations.
117
+
118
+ :param num_rows: Integer specifying the number of rows in the Pascal's triangle
119
+ :return: 2-D List (matrix) representing the Pascal's triangle
120
+
121
+ Return the Pascal's triangle of given rows
122
+ >>> generate_pascal_triangle_optimized(3)
123
+ [[1], [1, 1], [1, 2, 1]]
124
+ >>> generate_pascal_triangle_optimized(1)
125
+ [[1]]
126
+ >>> generate_pascal_triangle_optimized(0)
127
+ []
128
+ >>> generate_pascal_triangle_optimized(-5)
129
+ Traceback (most recent call last):
130
+ ...
131
+ ValueError: The input value of 'num_rows' should be greater than or equal to 0
132
+ >>> generate_pascal_triangle_optimized(7.89)
133
+ Traceback (most recent call last):
134
+ ...
135
+ TypeError: The input value of 'num_rows' should be 'int'
136
+ """
137
+
138
+ if not isinstance (num_rows , int ):
139
+ raise TypeError ("The input value of 'num_rows' should be 'int'" )
140
+
141
+ if num_rows == 0 :
142
+ return []
143
+ elif num_rows < 0 :
144
+ raise ValueError (
145
+ "The input value of 'num_rows' should be greater than or equal to 0"
146
+ )
147
+
148
+ result : list [list [int ]] = [[1 ]]
149
+
150
+ for row_index in range (1 , num_rows ):
151
+ temp_row = [0 ] + result [- 1 ] + [0 ]
152
+ row_length = row_index + 1
153
+ # Calculate the number of distinct elements in a row
154
+ distinct_elements = sum (divmod (row_length , 2 ))
155
+ row_first_half = [
156
+ temp_row [i - 1 ] + temp_row [i ] for i in range (1 , distinct_elements + 1 )
157
+ ]
158
+ row_second_half = row_first_half [: (row_index + 1 ) // 2 ]
159
+ row_second_half .reverse ()
160
+ row = row_first_half + row_second_half
161
+ result .append (row )
162
+
163
+ return result
164
+
165
+
166
+ def benchmark () -> None :
167
+ """
168
+ Benchmark multiple functions, with three different length int values.
169
+ """
170
+ from collections .abc import Callable
171
+ from timeit import timeit
172
+
173
+ def benchmark_a_function (func : Callable , value : int ) -> None :
174
+ call = f"{ func .__name__ } ({ value } )"
175
+ timing = timeit (f"__main__.{ call } " , setup = "import __main__" )
176
+ # print(f"{call:38} = {func(value)} -- {timing:.4f} seconds")
177
+ print (f"{ call :38} -- { timing :.4f} seconds" )
178
+
179
+ for value in range (15 ): # (1, 7, 14):
180
+ for func in (generate_pascal_triangle , generate_pascal_triangle_optimized ):
181
+ benchmark_a_function (func , value )
182
+ print ()
183
+
184
+
93
185
if __name__ == "__main__" :
94
186
import doctest
95
187
96
188
doctest .testmod ()
189
+ benchmark ()
0 commit comments