11"""
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:
64triangle[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
118"""
129
1310
@@ -38,6 +35,8 @@ def print_pascal_triangle(num_rows: int) -> None:
3835def generate_pascal_triangle (num_rows : int ) -> list [list [int ]]:
3936 """
4037 Create Pascal's triangle for different number of rows
38+ >>> generate_pascal_triangle(0)
39+ []
4140 >>> generate_pascal_triangle(1)
4241 [[1]]
4342 >>> generate_pascal_triangle(2)
@@ -48,7 +47,26 @@ def generate_pascal_triangle(num_rows: int) -> list[list[int]]:
4847 [[1], [1, 1], [1, 2, 1], [1, 3, 3, 1]]
4948 >>> generate_pascal_triangle(5)
5049 [[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'
5158 """
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+
5270 triangle : list [list [int ]] = []
5371 for current_row_idx in range (num_rows ):
5472 current_row = populate_current_row (triangle , current_row_idx )
@@ -90,7 +108,82 @@ def calculate_current_element(
90108 current_row [current_col_idx ] = above_to_left_elt + above_to_right_elt
91109
92110
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+
93185if __name__ == "__main__" :
94186 import doctest
95187
96188 doctest .testmod ()
189+ benchmark ()
0 commit comments