If you are open to an iterative solution, I cooked up up the following.
from itertools import chain
def pascal(n):
pad = (0,)
result = {1: [1]}
for i in range(2, n + 1):
previous = list(chain(pad, result[i - 1], pad))
result[i] = [sum(pair) for pair in zip(previous, previous[1:])]
return result
Demo:
>>> for n in range(1, 6):
...: print(pascal(n))
...:
...:
{1: [1]}
{1: [1], 2: [1, 1]}
{1: [1], 2: [1, 1], 3: [1, 2, 1]}
{1: [1], 2: [1, 1], 3: [1, 2, 1], 4: [1, 3, 3, 1]}
{1: [1], 2: [1, 1], 3: [1, 2, 1], 4: [1, 3, 3, 1], 5: [1, 4, 6, 4, 1]}
With a bit more lines, but also better memory efficiency:
from itertools import chain, tee
def pascal(n):
pad = (0,)
result = {1: [1]}
for i in range(2, n + 1):
previous = chain(pad, result[i - 1], pad)
c1, c2 = tee(previous)
next(c2)
result[i] = [sum(pair) for pair in zip(c1, c2)]
return result
Lastly, having a dict
with consecutive integer keys is not very useful, you could just use a list into which you index starting at 0
. Final solution:
def pascal(n):
pad = (0,)
result = [[1]]
for i in range(1, n):
previous = chain(pad, result[i - 1], pad)
c1, c2 = tee(previous)
next(c2)
result.append([sum(pair) for pair in zip(c1, c2)])
return result
Demo:
>>> for n in range(1, 6):
...: print(pascal(n))
...:
[[1]]
[[1], [1, 1]]
[[1], [1, 1], [1, 2, 1]]
[[1], [1, 1], [1, 2, 1], [1, 3, 3, 1]]
[[1], [1, 1], [1, 2, 1], [1, 3, 3, 1], [1, 4, 6, 4, 1]]
edit: improved efficiency by not creating two tuples per iteration, instantiating pad
once is enough.