# Python pattern challenge - Day 2

### Method 1: Using Nested Loops

def print_pattern(rows):
for i in range(rows):
num = 1
for j in range(1, i + 2):
print(num, end='')
num = num * (i + 1 - j) // j
print()

print_pattern(5)
# Change the argument to adjust the number of rows

let's break down the code step by step:

def print_pattern(rows):: This line defines a function named print_pattern that takes one argument rows, which represents the number of rows in the pattern.

for i in range(rows):: This loop iterates over each row of the pattern. It goes from 0 to rows - 1.

num = 1: Initializes the variable num to 1 for each row. This variable will hold the numbers to be printed on each row.

for j in range(1, i + 2):: This loop iterates over each column in the current row. It goes from 1 to i + 1.

print(num, end=''): Prints the value of num without a newline character. This ensures that all numbers in the same row are printed on the same line.

num = num * (i + 1 - j) // j: This line updates the value of num for the next column. It calculates the next number in the row based on the previous number using the formula (i + 1 - j) / j. This formula generates Pascal's triangle pattern.

print(): Prints a newline character after printing all numbers in the current row, moving to the next row.

print_pattern(5): Calls the print_pattern function with an argument of 5, which means it will print a pattern with 5 rows. You can change this argument to adjust the number of rows in the pattern.

The pattern generated by this code resembles Pascal's triangle, where each number in a row is the sum of the two numbers directly above it in the previous row.

### Method 2: Using Recursion

def print_pattern_recursive(rows):
if rows == 0:
return
print_pattern_recursive(rows - 1)
row = [1]
for i in range(1, rows):
row.append(row[-1] * (rows - i) // i)
print("".join(map(str, row)))

print_pattern_recursive(5)
# Change the argument to adjust the number of rows

let's break down the code step by step:

def print_pattern_recursive(rows):: This line defines a function named print_pattern_recursive that takes one argument rows, which represents the number of rows in the pattern.

if rows == 0:: This is the base case for the recursion. If rows is equal to 0, the function returns immediately, as there's no pattern to print.

return: This statement exits the function immediately if the base case is met.

print_pattern_recursive(rows - 1): This is the recursive call. It calls the print_pattern_recursive function with rows - 1, effectively reducing the number of rows to be printed in each recursive call.

row = [1]: Initializes a list row with a single element, 1. This represents the first row of the pattern.

for i in range(1, rows):: This loop iterates over each row index starting from 1 up to rows - 1.

row.append(row[-1] * (rows - i) // i): This line calculates and appends the next number to the row list. It uses the formula to generate Pascal's triangle pattern: (previous_number * (rows - i)) / i. This formula generates each number in the current row based on the numbers in the previous row.

print("".join(map(str, row))): This line prints the current row as a string by joining all elements in the row list and separating them with an empty string. This effectively prints the numbers of the current row without spaces between them.

print_pattern_recursive(5): Calls the print_pattern_recursive function with an argument of 5, which means it will print a pattern with 5 rows. You can change this argument to adjust the number of rows in the pattern.

The pattern generated by this code is similar to Pascal's triangle, where each number in a row is the sum of the two numbers directly above it in the previous row. However, this code generates each row recursively.

### Method 3: Using List Comprehension

def print_pattern_list_comprehension(rows):
pattern = [[1]]
[pattern.append([1] + [pattern[-1][j] + pattern[-1][j + 1] for j in range(len(pattern[-1]) - 1)] + [1]) for _ in range(1, rows)]
[print("".join(map(str, p))) for p in pattern]

print_pattern_list_comprehension(5)
# Change the argument to adjust the number of rows

Let's break down the code step by step:

def print_pattern_list_comprehension(rows):: This line defines a function named print_pattern_list_comprehension that takes one argument rows, representing the number of rows in the pattern.

pattern = [[1]]: Initializes a list pattern with a nested list containing a single element, which is [1]. This represents the first row of the pattern.

[pattern.append([1] + [pattern[-1][j] + pattern[-1][j + 1] for j in range(len(pattern[-1]) - 1)] + [1]) for _ in range(1, rows)]: This is a list comprehension that generates the pattern rows. It iterates over a range starting from 1 up to rows - 1.

pattern[-1] accesses the last row in the pattern list.

[pattern[-1][j] + pattern[-1][j + 1] for j in range(len(pattern[-1]) - 1)] generates the elements of the new row based on the previous row. It iterates over indices j of the previous row and calculates each element by summing adjacent elements.

[1] is appended at the beginning and end of the row to maintain the pattern structure.

pattern.append(...) adds the newly generated row to the pattern list.

[print("".join(map(str, p))) for p in pattern]: This is another list comprehension that prints each row of the pattern. It iterates over each row p in the pattern list, converts each element to a string, joins them without any separator using "".join(), and then prints the resulting string.

print_pattern_list_comprehension(5): Calls the print_pattern_list_comprehension function with an argument of 5, which means it will print a pattern with 5 rows. You can change this argument to adjust the number of rows in the pattern.

The pattern generated by this code is similar to Pascal's triangle, where each number in a row is the sum of the two numbers directly above it in the previous row. However, this code utilizes list comprehensions to generate and print the pattern efficiently.