Python Training at VMWare - Day 2

Jan 17-19, 2018 Vikrant Patil

These notes are available online at http://notes.pipal.in/2018/vmware-jan-python

© Pipal Academy LLP

Day 1 | Day 2 | Day 3

Conditions.. if else..

problem

  • Write a function filetype which will tell us type of file , given file name. it shoould support following file types.
      filetype     extension
      java          .java
      text          .txt
      python        .py
      haskell       .hs
      lisp          .lsp
      configuration .conf
    >>> filetype("Quicksort.py")
    "python"
    >>> filetype("QuickSort.java")
    "java"
  • Write a function minimum which finds minimum number from given two numbers.
  • What about minmimum3 which finds minimum number from three numbers.
In [2]:
def filetype(filename):
    if filename.lower().endswith(".java"):
        return "java"
    elif filename.lower().endswith(".txt"):
        return "text"
    elif filename.lower().endswith(".py"):
        return "python"
    elif filename.lower().endswith(".hs"):
        return "haskell"
    elif filename.lower().endswith(".lsp"):
        return "lisp"
    else:
        return None
    
In [3]:
def minimum(x,y):
    if x<y:
        return x
    else:
        return y
In [4]:
def minimum3(x,y,z):
    min1 = minimum(x,y)
    return minimum3(min1, z)

while loop

In [12]:
def print_fib(n):
    """
    prints fibonacci numbers less than n
    """
    
    prev, current = 1,1
    
    while prev<n:
        print(prev, end=",")
        prev, current = current, prev+current
In [13]:
print_fib(50)
1,1,2,3,5,8,13,21,34,

for loop

In [14]:
numbers = [1,1,2,3,5,8,13,21,34]
In [16]:
for number in numbers:
    print(number)
1
1
2
3
5
8
13
21
34
In [17]:
for c in "This statement is random string for testing for loops":
    print(c, end=",")
T,h,i,s, ,s,t,a,t,e,m,e,n,t, ,i,s, ,r,a,n,d,o,m, ,s,t,r,i,n,g, ,f,o,r, ,t,e,s,t,i,n,g, ,f,o,r, ,l,o,o,p,s,
In [19]:
persons ={"Anand":"C", "Alex":"Beaz","David":"Beazly"}
for name in persons:
    print(name, persons[name])
Anand C
Alex Beaz
David Beazly

problem

  • Write a python script ls.py which lists all files in current directoty.
    python ls.py
    add.py      
    day2.ipynb  
    hello1.py  
    module1.py   
    push
  • Write your own function mysum which sums up all elements from a list (using loops!)
    mysum([1,1,1,1,1])
    5
  • Write a function product which finds product all numbers from given list
    product([1,2,3,3])
    18
  • what about factorial? can you write a function for calculating factorial of a number
    factorial(4)
    24
In [23]:
%%file ls.py
import os
import sys

def listfiles(dirname):
    files = os.listdir(dirname)
    for file in files:
        print(file)
        
if __name__ == "__main__":
    if len(sys.argv)>1:
        listfiles(sys.argv[1])
    else:
        listfiles(os.getcwd())
        
Overwriting ls.py
In [24]:
!python ls.py
.ipynb_checkpoints
push
day1.ipynb
add.p
myscript.py
day2.ipynb
echo.py
day2.html
Untitled.html
hello.py
mymodule.py
hello1.py
moddule1.py
day3.ipynb
module1.py
module2.py
day3.html
Makefile
__pycache__
add.py
day1.html
ls.py
In [25]:
!python ls.py /tmp/
systemd-private-5d28fa0e32374f50a3885103b5e731e7-colord.service-CpDOG6
systemd-private-5d28fa0e32374f50a3885103b5e731e7-rtkit-daemon.service-uUhAbG
.XIM-unix
.font-unix
ssh-mPQxg6Ebgaa6
.ICE-unix
config-err-xKGGGh
.X11-unix
.X0-lock
.Test-unix
mintUpdate
In [26]:
def mysum(numbers):
    s = 0
    
    for n in numbers:
        s += n
    return s
In [27]:
mysum([1,1,1,1,1])
Out[27]:
5
In [28]:
def product(numbers):
    p = 1
    
    for n in numbers:
        p *= n
    return p
In [29]:
product([1,2,3,4])
Out[29]:
24
In [30]:
def factorial(n):
    return product(range(1,n+1))
In [31]:
factorial(5)
Out[31]:
120
In [32]:
for i in range(1,10):
    print(i,end=" ")
1 2 3 4 5 6 7 8 9 

lambda

In [33]:
add = lambda x,y: x+y
In [34]:
add(2,3)
Out[34]:
5
In [35]:
factorial = lambda n: product(range(1,n+1))
In [36]:
factorial(10)
Out[36]:
3628800
In [37]:
factorial(5)
Out[37]:
120

else in for loop

In [40]:
def print_primes(n):
    """
    prints prime numbers less than n
    """
    for i in range(2,n):
        for j in range(2,i):
            if i%j == 0:
                break
        else:
            print(i, end=",")
In [41]:
print_primes(50)
2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,

recap list methods

In [42]:
primes = [2,3,5,7,11,13,17,19,23,29,31,37]
In [43]:
primes.append(41)
In [44]:
primes.insert(0, 1)
In [45]:
primes.pop(0)
Out[45]:
1

problem

  • Write a function square to square the list
  • Write a fucntion evens to find even number from a list
In [46]:
def square(numbers):
    squares = []
    
    for n in numbers:
        squares.append(n*n)
        
    return squares
In [47]:
square(primes)
Out[47]:
[4, 9, 25, 49, 121, 169, 289, 361, 529, 841, 961, 1369, 1681]
In [48]:
square([1,2,3,4])
Out[48]:
[1, 4, 9, 16]
In [49]:
square(range(1,11))
Out[49]:
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
In [50]:
mysum(square(range(1,11)))
Out[50]:
385
In [51]:
def evens(numbers):
    e = []
    
    for n in numbers:
        if n%2 ==0:
            e.append(n)
    return e
In [52]:
evens(range(1,20))
Out[52]:
[2, 4, 6, 8, 10, 12, 14, 16, 18]

slicing

In [53]:
primes
Out[53]:
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41]
In [54]:
primes[2:7:2] # start at index 2 , end at 7 (excluding) at step of 2
Out[54]:
[5, 11, 17]
In [55]:
primes[2:7] # start at 2 , and at 7 at step of 1
Out[55]:
[5, 7, 11, 13, 17]
In [56]:
primes[:2] # take first 2
Out[56]:
[2, 3]
In [57]:
primes[2:] # drop first two
Out[57]:
[5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41]
In [58]:
primes[-1]
Out[58]:
41
In [59]:
primes[:-1] # all items except last
Out[59]:
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37]
In [60]:
primes[:-2]
Out[60]:
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31]
In [61]:
primes[:-5]
Out[61]:
[2, 3, 5, 7, 11, 13, 17, 19]
In [64]:
primes[:] # just a copy
Out[64]:
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41]
In [65]:
primes[::-1]
Out[65]:
[41, 37, 31, 29, 23, 19, 17, 13, 11, 7, 5, 3, 2]
In [66]:
word = "madam"
In [67]:
is_palindrome = lambda word : word==word[::-1]
In [68]:
is_palindrome(word)
Out[68]:
True
In [69]:
is_palindrome("121")
Out[69]:
True

problems

  • Write a function split_at which splits given list in two lists at given index
  • Write a function find_extension which finds extension of a file
  • What will happen if we execute this?
    s = "do geese see god"
    s[100]
    s[3:100]
In [70]:
def split_at(items, index):
    return items[:index], items[index:]
In [71]:
book = "Alice in wonderland"
In [72]:
book.split(" ")
Out[72]:
['Alice', 'in', 'wonderland']
In [73]:
path = "/usr/local/lib/python3/"
In [74]:
path.split("/")
Out[74]:
['', 'usr', 'local', 'lib', 'python3', '']
In [75]:
filenane = "anaconda.tar.gz"
In [77]:
tokens = filenane.split(".")
In [78]:
tokens.pop()
Out[78]:
'gz'
In [79]:
tokens
Out[79]:
['anaconda', 'tar']
In [80]:
filenane.split(".")[-1]
Out[80]:
'gz'
In [84]:
def find_extension(filename):
    return filename.split(".").pop()
In [85]:
find_extension = lambda f: f.split(".").pop()
In [86]:
find_extension("day1.ipynb")
Out[86]:
'ipynb'
In [87]:
s = "do geese see god"
In [89]:
len(s)
Out[89]:
16
In [91]:
s[3:100]
Out[91]:
'geese see god'

list comprehensions

In [92]:
for p in primes:
    #do something(p)
    pass
In [93]:
[p*p for p in primes]
Out[93]:
[4, 9, 25, 49, 121, 169, 289, 361, 529, 841, 961, 1369, 1681]
In [94]:
[2*p for p in primes]
Out[94]:
[4, 6, 10, 14, 22, 26, 34, 38, 46, 58, 62, 74, 82]
In [95]:
squares = [i*i for i in range(1,11)]
In [96]:
squares
Out[96]:
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
In [97]:
[factorial(i) for i in range(1,11)]
Out[97]:
[1, 2, 6, 24, 120, 720, 5040, 40320, 362880, 3628800]
In [99]:
[word.upper() for word in "Let me create some words from this statement".split()]
Out[99]:
['LET', 'ME', 'CREATE', 'SOME', 'WORDS', 'FROM', 'THIS', 'STATEMENT']
In [100]:
[i for i in range(10)]
Out[100]:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
In [102]:
[i for i in range(10) if i%2 ==0]
Out[102]:
[0, 2, 4, 6, 8]
In [103]:
words = "Let me create some words from this statement".split()
In [104]:
[word.upper() for word in words]
Out[104]:
['LET', 'ME', 'CREATE', 'SOME', 'WORDS', 'FROM', 'THIS', 'STATEMENT']
In [105]:
[word.upper() for word in words if word.startswith("s")]
Out[105]:
['SOME', 'STATEMENT']
In [106]:
import os
In [107]:
[[i*j for i in range(1,6)] for j in range(1,11)]
Out[107]:
[[1, 2, 3, 4, 5],
 [2, 4, 6, 8, 10],
 [3, 6, 9, 12, 15],
 [4, 8, 12, 16, 20],
 [5, 10, 15, 20, 25],
 [6, 12, 18, 24, 30],
 [7, 14, 21, 28, 35],
 [8, 16, 24, 32, 40],
 [9, 18, 27, 36, 45],
 [10, 20, 30, 40, 50]]
In [108]:
tables = []
for j in range(1,11):
    e = []
    for i in range(1,6):
        e.append(i*j)
    tables.append(e)
In [109]:
tables
Out[109]:
[[1, 2, 3, 4, 5],
 [2, 4, 6, 8, 10],
 [3, 6, 9, 12, 15],
 [4, 8, 12, 16, 20],
 [5, 10, 15, 20, 25],
 [6, 12, 18, 24, 30],
 [7, 14, 21, 28, 35],
 [8, 16, 24, 32, 40],
 [9, 18, 27, 36, 45],
 [10, 20, 30, 40, 50]]

problems

  • Write a function listpy which lists only python files from given directory.
  • Write a function factors which finds factors of given number, include 1 and self also.
  • prime number has only two factors 1 and self. Use this to write a function is_prime which determines if given number is prime or not
  • Write a function primes which generates prime numbers less than given number
In [110]:
import os
def listpy(directory):
    files = os.listdir(directory)
    return [file for file in files if file.endswith(".py")]
In [111]:
listpy(os.getcwd())
Out[111]:
['myscript.py',
 'echo.py',
 'hello.py',
 'mymodule.py',
 'hello1.py',
 'moddule1.py',
 'module1.py',
 'module2.py',
 'add.py',
 'ls.py']
In [112]:
def factors(n):
    return [f for f in range(1,n+1) if n%f==0]
In [113]:
factors(10)
Out[113]:
[1, 2, 5, 10]
In [114]:
factors(7)
Out[114]:
[1, 7]
In [115]:
def is_prime(n):
    return factors(n)==[1,n]
In [116]:
def is_prime(n):
    return len(factors(n))==2
In [117]:
primes = lambda n: [p for p in range(1,n) if is_prime(p)]
In [118]:
primes(50)
Out[118]:
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47]

bonus problems

  • Generate a unit matrix of 5x5 using list comprehensions
  • Find sum of all multiples of 7 or 11 less than 1000
  • transpose a 2d list
  • rotate 2D list by 90 degree.
In [119]:
[i for i in range(5)]
Out[119]:
[0, 1, 2, 3, 4]
In [120]:
[[i for i in range(5)] for j in range(5)]
Out[120]:
[[0, 1, 2, 3, 4],
 [0, 1, 2, 3, 4],
 [0, 1, 2, 3, 4],
 [0, 1, 2, 3, 4],
 [0, 1, 2, 3, 4]]
In [121]:
[[i+j for i in range(5)] for j in range(5)]
Out[121]:
[[0, 1, 2, 3, 4],
 [1, 2, 3, 4, 5],
 [2, 3, 4, 5, 6],
 [3, 4, 5, 6, 7],
 [4, 5, 6, 7, 8]]
In [122]:
def f(x,y):
    return x+y
In [123]:
[[ f(i,j) for i in range(5)] for j in range(5)]
Out[123]:
[[0, 1, 2, 3, 4],
 [1, 2, 3, 4, 5],
 [2, 3, 4, 5, 6],
 [3, 4, 5, 6, 7],
 [4, 5, 6, 7, 8]]
In [124]:
def diagonal(x,y):
    if x==y:
        return 1
    else:
        return 0
In [125]:
[[ diagonal(i,j) for i in range(5)] for j in range(5)]
Out[125]:
[[1, 0, 0, 0, 0],
 [0, 1, 0, 0, 0],
 [0, 0, 1, 0, 0],
 [0, 0, 0, 1, 0],
 [0, 0, 0, 0, 1]]
In [133]:
data = [[i*j for i in range(5)] for j in range(5)]
In [135]:
for i in range(5):
    data[i][0] = i
In [136]:
data
Out[136]:
[[0, 0, 0, 0, 0],
 [1, 1, 2, 3, 4],
 [2, 2, 4, 6, 8],
 [3, 3, 6, 9, 12],
 [4, 4, 8, 12, 16]]
In [137]:
data[0]
Out[137]:
[0, 0, 0, 0, 0]
In [138]:
data[0][0]
Out[138]:
0
In [139]:
numrows = 5
[data[i][0] for i in range(numrows)]
Out[139]:
[0, 1, 2, 3, 4]
In [140]:
data
Out[140]:
[[0, 0, 0, 0, 0],
 [1, 1, 2, 3, 4],
 [2, 2, 4, 6, 8],
 [3, 3, 6, 9, 12],
 [4, 4, 8, 12, 16]]
In [143]:
[data[i][2] for i in range(numrows)]
Out[143]:
[0, 2, 4, 6, 8]
In [144]:
def column(data, colnum):
    rowcount = len(data)
    return [data[i][colnum] for i in range(rowcount)]
In [146]:
column(data,0)
Out[146]:
[0, 1, 2, 3, 4]
In [147]:
colcount = len(data[0])
[column(data,i) for i in range(colcount)]
Out[147]:
[[0, 1, 2, 3, 4],
 [0, 1, 2, 3, 4],
 [0, 2, 4, 6, 8],
 [0, 3, 6, 9, 12],
 [0, 4, 8, 12, 16]]
In [148]:
def transpose(data):
    columncount = len(data[0])
    return [column(data, i) for i in range(columncount)]
In [149]:
transpose(data)
Out[149]:
[[0, 1, 2, 3, 4],
 [0, 1, 2, 3, 4],
 [0, 2, 4, 6, 8],
 [0, 3, 6, 9, 12],
 [0, 4, 8, 12, 16]]
In [150]:
data
Out[150]:
[[0, 0, 0, 0, 0],
 [1, 1, 2, 3, 4],
 [2, 2, 4, 6, 8],
 [3, 3, 6, 9, 12],
 [4, 4, 8, 12, 16]]
In [151]:
sum([i for i in range(1000) if i%7==0 or i%11==0])
Out[151]:
110110
In [152]:
data
Out[152]:
[[0, 0, 0, 0, 0],
 [1, 1, 2, 3, 4],
 [2, 2, 4, 6, 8],
 [3, 3, 6, 9, 12],
 [4, 4, 8, 12, 16]]
In [153]:
row = list(range(5))
In [154]:
row
Out[154]:
[0, 1, 2, 3, 4]
In [155]:
[i for i in row]
Out[155]:
[0, 1, 2, 3, 4]
In [156]:
[row[i] for i in range(len(row))]
Out[156]:
[0, 1, 2, 3, 4]
In [157]:
l = len(row)
[row[l-i-1] for i in range(l)]
Out[157]:
[4, 3, 2, 1, 0]

Iteration patterns

In [158]:
for i in range(5):
    print(i)
0
1
2
3
4
In [159]:
for i in reversed(range(5)):
    print(i)
4
3
2
1
0
In [160]:
for c in reversed("some string"):
    print(c,end=",")
g,n,i,r,t,s, ,e,m,o,s,
In [161]:
lines = """
one
two
three
four
five
"""
In [162]:
lines = lines.strip().split("\n")
In [163]:
lines
Out[163]:
['one', 'two', 'three', 'four', 'five']
In [164]:
for index,line in enumerate(lines):
    print(index, line)
    
0 one
1 two
2 three
3 four
4 five
In [165]:
s = "  hello    "
In [166]:
s.strip()
Out[166]:
'hello'
In [167]:
first = ["Elsa", "Alisa","Beauty"]
last = ["Frozen","Hacker","Nurd"]
In [168]:
for name, surname in zip(first, last):
    print(name, surname)
Elsa Frozen
Alisa Hacker
Beauty Nurd
In [169]:
zipped = zip([1,2,3,4],["one","two","three","four"])
In [170]:
zipped
Out[170]:
<zip at 0x7fc4ec09bec8>
In [171]:
list(zipped)
Out[171]:
[(1, 'one'), (2, 'two'), (3, 'three'), (4, 'four')]
In [173]:
zipped = zip([1,2,3,4],["one","two","three","four"])
In [174]:
for item1, item2 in zipped:
    print(item1, item2)
1 one
2 two
3 three
4 four
In [175]:
def vectoradd(v1, v2):
    return [i+j for i,j in zip(v1,v2)]
In [177]:
vectoradd(range(4),range(4))
Out[177]:
[0, 2, 4, 6]

Testing

In [186]:
%%file functions.py
"""
implements few basic function with its test cases
"""


def add(x,y):
    """
    this function adds two numbers
    >>> add(0,1)
    1
    >>> add(-1,1)
    0
    """
    return x+y

def square(x):
    """
    >>> square(-1)
    1
    >>> square(2)
    4
    """
    return x*x

def mult(x,y):
    """
    >>> mult(1,2)
    2
    """
    return x+y
Overwriting functions.py
In [187]:
!python -m doctest functions.py
**********************************************************************
File "/home/vikrant/trainings/2018/vmware-jan-python/functions.py", line 27, in functions.mult
Failed example:
    mult(1,2)
Expected:
    2
Got:
    3
**********************************************************************
1 items had failures:
   1 of   1 in functions.mult
***Test Failed*** 1 failures.
In [189]:
!pydoc functions
Help on module functions:

NNAAMMEE
    functions - implements few basic function with its test cases

FFUUNNCCTTIIOONNSS
    aadddd(x, y)
        this function adds two numbers
        >>> add(0,1)
        1
        >>> add(-1,1)
        0
    
    mmuulltt(x, y)
        >>> mult(1,2)
        2
    
    ssqquuaarree(x)
        >>> square(-1)
        1
        >>> square(2)
        4

FFIILLEE
    /home/vikrant/trainings/2018/vmware-jan-python/functions.py


In [199]:
%%file functions.py
"""
implements few basic function with its test cases
"""


def add(x,y):
    """
    this function adds two numbers
    >>> add(0,1)
    1
    >>> add(-1,1)
    0
    """
    return x+y

def square(x):
    """
    >>> square(-1)
    1
    >>> square(2)
    4
    """
    return x*x

def mult(x,y):
    """
    >>> mult(1,2)
    2
    """
    return x+y

def test_add():
    if add(1,-1)==0:
        print("passed")
    if add(0,1)==1:
        print("passed")
        
def test_add1():
    assert add(1,-1) == 0
    assert add(1,0) == 1
    
def test_square():
    assert square(-1) == 1
 
        
Overwriting functions.py
In [200]:
!py.test -v functions.py
============================= test session starts ==============================
platform linux -- Python 3.6.1, pytest-3.0.7, py-1.4.33, pluggy-0.4.0 -- /home/vikrant/usr/local/anaconda3/bin/python
cachedir: .cache
rootdir: /home/vikrant/trainings/2018/vmware-jan-python, inifile:
collected 3 items 

functions.py::test_add PASSED
functions.py::test_add1 PASSED
functions.py::test_square PASSED

=========================== 3 passed in 0.01 seconds ===========================

if you don't have pytest on your machine you can install it using

pip3 install pytest

string formatting

In [207]:
for i in range(1,11):
    print(i,i*i,i*i*i)
1 1 1
2 4 8
3 9 27
4 16 64
5 25 125
6 36 216
7 49 343
8 64 512
9 81 729
10 100 1000
In [208]:
for i in range(1,11):
    print(str(i).rjust(2), str(i*i).rjust(3), str(i*i*i).rjust(4))
 1   1    1
 2   4    8
 3   9   27
 4  16   64
 5  25  125
 6  36  216
 7  49  343
 8  64  512
 9  81  729
10 100 1000
In [209]:
name = "Alice"
In [210]:
name.ljust(10)
Out[210]:
'Alice     '
In [211]:
name.rjust(10)
Out[211]:
'     Alice'
In [212]:
name.center(10)
Out[212]:
'  Alice   '
In [213]:
"wizard of oz is {}".format("python")
Out[213]:
'wizard of oz is python'
In [214]:
"wizard of {} is in {}".format("python", "oz")
Out[214]:
'wizard of python is in oz'
In [215]:
"wizard of {1} is in {0}".format("oz", "python")
Out[215]:
'wizard of python is in oz'
In [216]:
"purpose of life is {0}, my computation in {1} says so!".format(42, "python")
Out[216]:
'purpose of life is 42, my computation in python says so!'
In [217]:
for i in range(1,11):
    print("{0:2d} {1:3d} {2:4d}".format(i, i*i, i*i*i))
 1   1    1
 2   4    8
 3   9   27
 4  16   64
 5  25  125
 6  36  216
 7  49  343
 8  64  512
 9  81  729
10 100 1000
In [218]:
for i in range(1,11):
    print("{integer:2d} {square:3d} {cube:4d}".format(integer=i, square=i*i, cube=i**3))
 1   1    1
 2   4    8
 3   9   27
 4  16   64
 5  25  125
 6  36  216
 7  49  343
 8  64  512
 9  81  729
10 100 1000
In [219]:
"12".zfill(5)
Out[219]:
'00012'

problem

  • Write a function pascal to generate pascal triangle of base n.
>>> pascal(3)
[[1],[1,1],[1,2,1]]
  • Write a function print_pascal to prety print pascal tringle.
    >>> t = pascal(5)
    >>> print_pascal(t)
        1
      1   1
    1   2   1
  1   3   3   1
1   4   6   4   1
In [220]:
def pascal(n):
    triangle = [[1]]

    for i in range(1,n):
        lastrow = triangle[-1]
        pre = [0] + lastrow
        post = lastrow + [0]
        newrow  = [i+j for i,j in zip(pre, post)]
        triangle.append(newrow)
        
    return triangle
In [221]:
pascal(3)
Out[221]:
[[1], [1, 1], [1, 2, 1]]
In [222]:
pascal(6)
Out[222]:
[[1], [1, 1], [1, 2, 1], [1, 3, 3, 1], [1, 4, 6, 4, 1], [1, 5, 10, 10, 5, 1]]
In [229]:
def print_pascal(triangle):
 
    def formatrow(row):
        s = ""
        for item in row:
            s += ("{item:{digits}d} ".format(item=item, digits=maxdigits))
        return s
    
    lastrow = triangle[-1]
    maxnum = max(lastrow)
    maxdigits = len(str(maxnum))
    width = len(lastrow)*maxdigits + len(lastrow)-1
    
    for row in triangle:
        print(formatrow(row).center(width))
        
In [230]:
t = pascal(6)
print_pascal(t)
        1        
       1  1      
     1  2  1     
    1  3  3  1   
  1  4  6  4  1  
 1  5 10 10  5  1 
In [231]:
print_pascal(pascal(12))
                        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 
In [ ]: