Skip to content

Commit

Permalink
Modified 'pascal_triangle.py' program (TheAlgorithms#7901)
Browse files Browse the repository at this point in the history
* Added pascals_triangle.py program to maths directory

* Deleted 'pascals_triangle.py' because of duplication. Added a optimized function to generate pascal's triangle to 'pascal_triangle.py' program. Added some aadditional doctests to the existing function. Added some type check functionality to the existing function.

* Modified type check hints in 'generate_pascal_triangle_optimized' function'

q

* Modified 'pascal_triangle' prgram

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* Update pascal_triangle.py

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Christian Clauss <[email protected]>
  • Loading branch information
3 people authored Oct 31, 2022
1 parent a31edd4 commit fecbf59
Showing 1 changed file with 101 additions and 8 deletions.
109 changes: 101 additions & 8 deletions other/pascal_triangle.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
"""
This implementation demonstrates how to generate the
elements of a Pascal's triangle. The element having
a row index of r and column index of c can be derived
as follows:
This implementation demonstrates how to generate the elements of a Pascal's triangle.
The element havingva row index of r and column index of c can be derivedvas follows:
triangle[r][c] = triangle[r-1][c-1]+triangle[r-1][c]
What is Pascal's triangle?
- It is a triangular array containing binomial coefficients.
Refer to (https://en.wikipedia.org/wiki/Pascal%27s_triangle)
for more info about this triangle.
A Pascal's triangle is a triangular array containing binomial coefficients.
https://en.wikipedia.org/wiki/Pascal%27s_triangle
"""


Expand Down Expand Up @@ -38,6 +35,8 @@ def print_pascal_triangle(num_rows: int) -> None:
def generate_pascal_triangle(num_rows: int) -> list[list[int]]:
"""
Create Pascal's triangle for different number of rows
>>> generate_pascal_triangle(0)
[]
>>> generate_pascal_triangle(1)
[[1]]
>>> generate_pascal_triangle(2)
Expand All @@ -48,7 +47,26 @@ def generate_pascal_triangle(num_rows: int) -> list[list[int]]:
[[1], [1, 1], [1, 2, 1], [1, 3, 3, 1]]
>>> generate_pascal_triangle(5)
[[1], [1, 1], [1, 2, 1], [1, 3, 3, 1], [1, 4, 6, 4, 1]]
>>> generate_pascal_triangle(-5)
Traceback (most recent call last):
...
ValueError: The input value of 'num_rows' should be greater than or equal to 0
>>> generate_pascal_triangle(7.89)
Traceback (most recent call last):
...
TypeError: The input value of 'num_rows' should be 'int'
"""

if not isinstance(num_rows, int):
raise TypeError("The input value of 'num_rows' should be 'int'")

if num_rows == 0:
return []
elif num_rows < 0:
raise ValueError(
"The input value of 'num_rows' should be greater than or equal to 0"
)

triangle: list[list[int]] = []
for current_row_idx in range(num_rows):
current_row = populate_current_row(triangle, current_row_idx)
Expand Down Expand Up @@ -90,7 +108,82 @@ def calculate_current_element(
current_row[current_col_idx] = above_to_left_elt + above_to_right_elt


def generate_pascal_triangle_optimized(num_rows: int) -> list[list[int]]:
"""
This function returns a matrix representing the corresponding pascal's triangle
according to the given input of number of rows of Pascal's triangle to be generated.
It reduces the operations done to generate a row by half
by eliminating redundant calculations.
:param num_rows: Integer specifying the number of rows in the Pascal's triangle
:return: 2-D List (matrix) representing the Pascal's triangle
Return the Pascal's triangle of given rows
>>> generate_pascal_triangle_optimized(3)
[[1], [1, 1], [1, 2, 1]]
>>> generate_pascal_triangle_optimized(1)
[[1]]
>>> generate_pascal_triangle_optimized(0)
[]
>>> generate_pascal_triangle_optimized(-5)
Traceback (most recent call last):
...
ValueError: The input value of 'num_rows' should be greater than or equal to 0
>>> generate_pascal_triangle_optimized(7.89)
Traceback (most recent call last):
...
TypeError: The input value of 'num_rows' should be 'int'
"""

if not isinstance(num_rows, int):
raise TypeError("The input value of 'num_rows' should be 'int'")

if num_rows == 0:
return []
elif num_rows < 0:
raise ValueError(
"The input value of 'num_rows' should be greater than or equal to 0"
)

result: list[list[int]] = [[1]]

for row_index in range(1, num_rows):
temp_row = [0] + result[-1] + [0]
row_length = row_index + 1
# Calculate the number of distinct elements in a row
distinct_elements = sum(divmod(row_length, 2))
row_first_half = [
temp_row[i - 1] + temp_row[i] for i in range(1, distinct_elements + 1)
]
row_second_half = row_first_half[: (row_index + 1) // 2]
row_second_half.reverse()
row = row_first_half + row_second_half
result.append(row)

return result


def benchmark() -> None:
"""
Benchmark multiple functions, with three different length int values.
"""
from collections.abc import Callable
from timeit import timeit

def benchmark_a_function(func: Callable, value: int) -> None:
call = f"{func.__name__}({value})"
timing = timeit(f"__main__.{call}", setup="import __main__")
# print(f"{call:38} = {func(value)} -- {timing:.4f} seconds")
print(f"{call:38} -- {timing:.4f} seconds")

for value in range(15): # (1, 7, 14):
for func in (generate_pascal_triangle, generate_pascal_triangle_optimized):
benchmark_a_function(func, value)
print()


if __name__ == "__main__":
import doctest

doctest.testmod()
benchmark()

0 comments on commit fecbf59

Please sign in to comment.