# Pascal’s Triangle for Python

Posted on

### Question :

Pascal’s Triangle for Python

As a learning experience for Python, I am trying to code my own version of Pascal’s triangle. It took me a few hours (as I am just starting), but I came out with this code:

``````pascals_triangle = []

def blank_list_gen(x):
while len(pascals_triangle) < x:
pascals_triangle.append()

def pascals_tri_gen(rows):
blank_list_gen(rows)
for element in range(rows):
count = 1
while count < rows - element:
pascals_triangle[count + element].append(0)
count += 1
for row in pascals_triangle:
row.insert(0, 1)
row.append(1)
pascals_triangle.insert(0, [1, 1])
pascals_triangle.insert(0, )

pascals_tri_gen(6)

for row in pascals_triangle:
print(row)
``````

which returns

``````
[1, 1]
[1, 0, 1]
[1, 0, 0, 1]
[1, 0, 0, 0, 1]
[1, 0, 0, 0, 0, 1]
[1, 0, 0, 0, 0, 0, 1]
[1, 0, 0, 0, 0, 0, 0, 1]
``````

However, I have no idea where to go from here. I have been banging my head against the wall for hours. I want to emphasize that I do NOT want you to do it for me; just push me in the right direction. As a list, my code returns

``````[, [1, 1], [1, 0, 1], [1, 0, 0, 1], [1, 0, 0, 0, 1], [1, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 1]]
``````

Thanks.

EDIT: I took some good advice, and I completely rewrote my code, but I am now running into another problem. Here is my code.

``````import math

pascals_tri_formula = []

def combination(n, r):
return int((math.factorial(n)) / ((math.factorial(r)) * math.factorial(n - r)))

def for_test(x, y):
for y in range(x):
return combination(x, y)

def pascals_triangle(rows):
count = 0
while count <= rows:
for element in range(count + 1):
[pascals_tri_formula.append(combination(count, element))]
count += 1

pascals_triangle(3)

print(pascals_tri_formula)
``````

However, I am finding that the output is a bit undesirable:

``````[1, 1, 1, 1, 2, 1, 1, 3, 3, 1]
``````

How can I fix this?

OK code review:

``````import math

# pascals_tri_formula = [] # don't collect in a global variable.

def combination(n, r): # correct calculation of combinations, n choose k
return int((math.factorial(n)) / ((math.factorial(r)) * math.factorial(n - r)))

def for_test(x, y): # don't see where this is being used...
for y in range(x):
return combination(x, y)

def pascals_triangle(rows):
result = [] # need something to collect our results in
# count = 0 # avoidable! better to use a for loop,
# while count <= rows: # can avoid initializing and incrementing
for count in range(rows): # start at 0, up to but not including rows number.
# this is really where you went wrong:
row = [] # need a row element to collect the row in
for element in range(count + 1):
# putting this in a list doesn't do anything.
# [pascals_tri_formula.append(combination(count, element))]
row.append(combination(count, element))
result.append(row)
# count += 1 # avoidable
return result

# now we can print a result:
for row in pascals_triangle(3):
print(row)
``````

prints:

``````
[1, 1]
[1, 2, 1]
``````

## Explanation of Pascal’s triangle:

This is the formula for “n choose k” (i.e. how many different ways (disregarding order), from an ordered list of n items, can we choose k items):

``````from math import factorial

def combination(n, k):
"""n choose k, returns int"""
return int((factorial(n)) / ((factorial(k)) * factorial(n - k)))
``````

A commenter asked if this is related to itertools.combinations – indeed it is. “n choose k” can be calculated by taking the length of a list of elements from combinations:

``````from itertools import combinations

def pascals_triangle_cell(n, k):
"""n choose k, returns int"""
result = len(list(combinations(range(n), k)))
# our result is equal to that returned by the other combination calculation:
assert result == combination(n, k)
return result
``````

Let’s see this demonstrated:

``````from pprint import pprint

ptc = pascals_triangle_cell

>>> pprint([[ptc(0, 0),],
[ptc(1, 0), ptc(1, 1)],
[ptc(2, 0), ptc(2, 1), ptc(2, 2)],
[ptc(3, 0), ptc(3, 1), ptc(3, 2), ptc(3, 3)],
[ptc(4, 0), ptc(4, 1), ptc(4, 2), ptc(4, 3), ptc(4, 4)]],
width = 20)
[,
[1, 1],
[1, 2, 1],
[1, 3, 3, 1],
[1, 4, 6, 4, 1]]
``````

We can avoid repeating ourselves with a nested list comprehension:

``````def pascals_triangle(rows):
return [[ptc(row, k) for k in range(row + 1)] for row in range(rows)]

>>> pprint(pascals_triangle(15))
[,
[1, 1],
[1, 2, 1],
[1, 3, 3, 1],
[1, 4, 6, 4, 1],
[1, 5, 10, 10, 5, 1],
[1, 6, 15, 20, 15, 6, 1],
[1, 7, 21, 35, 35, 21, 7, 1],
[1, 8, 28, 56, 70, 56, 28, 8, 1],
[1, 9, 36, 84, 126, 126, 84, 36, 9, 1],
[1, 10, 45, 120, 210, 252, 210, 120, 45, 10, 1],
[1, 11, 55, 165, 330, 462, 462, 330, 165, 55, 11, 1],
[1, 12, 66, 220, 495, 792, 924, 792, 495, 220, 66, 12, 1],
[1, 13, 78, 286, 715, 1287, 1716, 1716, 1287, 715, 286, 78, 13, 1],
[1, 14, 91, 364, 1001, 2002, 3003, 3432, 3003, 2002, 1001, 364, 91, 14, 1]]
``````

## Recursively defined:

We can define this recursively (a less efficient, but perhaps more mathematically elegant definition) using the relationships illustrated by the triangle:

`````` def choose(n, k): # note no dependencies on any of the prior code
if k in (0, n):
return 1
return choose(n-1, k-1) + choose(n-1, k)
``````

And for fun, you can see each row take progressively longer to execute, because each row has to recompute nearly each element from the prior row twice each time:

``````for row in range(40):
for k in range(row + 1):
# flush is a Python 3 only argument, you can leave it out,
# but it lets us see each element print as it finishes calculating
print(choose(row, k), end=' ', flush=True)
print()

1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
1 5 10 10 5 1
1 6 15 20 15 6 1
1 7 21 35 35 21 7 1
1 8 28 56 70 56 28 8 1
1 9 36 84 126 126 84 36 9 1
1 10 45 120 210 252 210 120 45 10 1
1 11 55 165 330 462 462 330 165 55 11 1
1 12 66 220 495 792 924 792 495 220 66 12 1
1 13 78 286 715 1287 1716 1716 1287 715 286 78 13 1
1 14 91 364 1001 2002 3003 3432 3003 2002 1001 364 91 14 1
1 15 105 455 1365 3003 5005 6435 6435 5005 3003 1365 455 105 15 1
1 16 120 560 1820 4368 8008 11440 12870 11440 8008 4368 1820 560 120 16 1
1 17 136 680 2380 6188 12376 19448 24310 24310 19448 12376 6188 2380 680 136 17 1
1 18 153 816 3060 8568 18564 31824 43758 48620 43758 31824 18564 8568 3060 816 ...
``````

Ctrl-C to quit when you get tired of watching it, it gets very slow very fast…

I know you want to implement yourself, but the best way for me to explain is to walk through an implementation. Here’s how I would do it, and this implementation relies on my fairly complete knowledge of how Python’s functions work, so you probably won’t want to use this code yourself, but it may get you pointed in the right direction.

``````def pascals_triangle(n_rows):
results = [] # a container to collect the rows
for _ in range(n_rows):
row =  # a starter 1 in the row
if results: # then we're in the second row or beyond
last_row = results[-1] # reference the previous row
# this is the complicated part, it relies on the fact that zip
# stops at the shortest iterable, so for the second row, we have
# nothing in this list comprension, but the third row sums 1 and 1
# and the fourth row sums in pairs. It's a sliding window.
row.extend([sum(pair) for pair in zip(last_row, last_row[1:])])
# finally append the final 1 to the outside
row.append(1)
results.append(row) # add the row to the results.
return results
``````

usage:

``````>>> for i in pascals_triangle(6):
...     print(i)
...

[1, 1]
[1, 2, 1]
[1, 3, 3, 1]
[1, 4, 6, 4, 1]
[1, 5, 10, 10, 5, 1]
``````

Without using zip, but using generator:

``````def gen(n,r=[]):
for x in range(n):
l = len(r)
r = [1 if i == 0 or i == l else r[i-1]+r[i] for i in range(l+1)]
yield r
``````

example:

``````print(list(gen(15)))
``````

output:

``````[, [1, 1], [1, 2, 1], [1, 3, 3, 1], [1, 4, 6, 4, 1], [1, 5, 10, 10, 5, 1], [1, 6, 15, 20, 15, 6, 1], [1, 7, 21, 35, 35, 21, 7, 1], [1, 8, 28, 56, 70, 56, 28, 8, 1], [1, 9, 36, 84, 126, 126, 84, 36, 9, 1], [1, 10, 45, 120, 210, 252, 210, 120, 45, 10, 1], [1, 11, 55, 165, 330, 462, 462, 330, 165, 55, 11, 1], [1, 12, 66, 220, 495, 792, 924, 792, 495, 220, 66, 12, 1], [1, 13, 78, 286, 715, 1287, 1716, 1716, 1287, 715, 286, 78, 13, 1], [1, 14, 91, 364, 1001, 2002, 3003, 3432, 3003, 2002, 1001, 364, 91, 14, 1]]
``````

DISPLAY AS TRIANGLE

To draw it in beautiful triangle(works only for n < 7, beyond that it gets distroted. ref draw_beautiful for n>7)

for n < 7

``````def draw(n):
for p in gen(n):
print(' '.join(map(str,p)).center(n*2)+'n')
``````

eg:

`draw(10`)

output:

``````      1

1 1

1 2 1

1 3 3 1

1 4 6 4 1

1 5 10 10 5 1
``````

for any size

since we need to know the max width, we can’t make use of generator

``````def draw_beautiful(n):
ps = list(gen(n))
max = len(' '.join(map(str,ps[-1])))
for p in ps:
print(' '.join(map(str,p)).center(max)+'n')
``````

example (2) :
works for any number:

``````draw_beautiful(100)
`````` Here is my attempt:

``````def generate_pascal_triangle(rows):
if rows == 1: return []

triangle = [, [1, 1]] # pre-populate with the first two rows

row = [1, 1] # Starts with the second row and calculate the next

for i in range(2, rows):
row =  + [sum(column) for column in zip(row[1:], row)] + 
triangle.append(row)

return triangle

for row in generate_pascal_triangle(6):
print row
``````

# Discussion

• The first two rows of the triangle is hard-coded
• The `zip()` call basically pairs two adjacent numbers together
• We still have to add 1 to the beginning and another 1 to the end because the `zip()` call only generates the middle of the next row

``````# combining the insights from Aaron Hall and Hai Vu,
# we get:

def pastri(n):
rows = []
for _ in range(1, n+1):
rows.append( +
[sum(pair) for pair in zip(rows[-1], rows[-1][1:])] +
)
return rows

# thanks! learnt that "shape shifting" data,
# can yield/generate elegant solutions.
``````

``````def pascal(n):
if n==0:
return 
else:
N = pascal(n-1)
return  + [N[i] + N[i+1] for i in range(n-1)] + 

def pascal_triangle(n):
for i in range(n):
print pascal(i)
``````

Beginner Python student here. Here’s my attempt at it, a very literal approach, using two For loops:

``````pascal = []
num = int(input("Number of iterations: "))
print(pascal) # the very first row
for i in range(1,num+1):
pascal.append() # start off with 1
for j in range(len(pascal[i-1])-1):
# the number of times we need to run this loop is (# of elements in the row above)-1
pascal[i].append(pascal[i-1][j]+pascal[i-1][j+1])
pascal[i].append(1) # and cap it with 1
print(pascal[i])
``````

Here is an elegant and efficient recursive solution. I’m using the very handy toolz library.

``````from toolz import memoize, sliding_window

@memoize
def pascals_triangle(n):
"""Returns the n'th row of Pascal's triangle."""
if n == 0:
return 
prev_row = pascals_triangle(n-1)
return [1, *map(sum, sliding_window(2, prev_row)), 1]
``````

`pascals_triangle(300)` takes about 15 ms on a macbook pro (2.9 GHz Intel Core i5). Note that you can’t go much higher without increasing the default recursion depth limit.