Pascal's Triangle for Python

后端 未结 11 1520
轮回少年
轮回少年 2020-11-30 06:13

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:

相关标签:
11条回答
  • 2020-11-30 06:28
    # combining the insights from Aaron Hall and Hai Vu,
    # we get:
    
    def pastri(n):
        rows = [[1]]
        for _ in range(1, n+1):
            rows.append([1] +
                        [sum(pair) for pair in zip(rows[-1], rows[-1][1:])] +
                        [1])
        return rows
    
    # thanks! learnt that "shape shifting" data,
    # can yield/generate elegant solutions.
    
    0 讨论(0)
  • 2020-11-30 06:30

    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]
    [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],
     [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],
     [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...

    0 讨论(0)
  • 2020-11-30 06:30

    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], [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)
    

    0 讨论(0)
  • 2020-11-30 06:35
    def pascal(n):
        if n==0:
            return [1]
        else:
            N = pascal(n-1)
            return [1] + [N[i] + N[i+1] for i in range(n-1)] + [1]
    
    
    def pascal_triangle(n):
        for i in range(n):
            print pascal(i)
    
    0 讨论(0)
  • 2020-11-30 06:41
    # call the function ! Indent properly , everything should be inside the function
    def triangle():
    
              matrix=[[0 for i in range(0,20)]for e in range(0,10)]         # This method assigns 0's to all Rows and Columns , the range is mentioned
              div=20/2           # it give us the most middle columns 
              matrix[0][div]=1        # assigning 1 to the middle of first row 
              for i in range(1,len(matrix)-1): # it goes column by column
                   for j in range(1,20-1):  #  this loop goes row by row
                       matrix[i][j]=matrix[i-1][j-1]+matrix[i-1][j+1]               # this is the formula , first element of the matrix gets , addition of i index (which is 0 at first ) with third value on the the related row
        # replacing 0s with spaces :) 
              for i in range(0,len(matrix)):
                  for j in range(0,20):
                       if matrix[i][j]==0:       #  Replacing 0's with spaces
                            matrix[i][j]=" "
    
              for i in range(0,len(matrix)-1):           # using spaces , the triangle will printed beautifully 
                    for j in range(0,20):
                        print 1*" ",matrix[i][j],1*" ", # giving some spaces in two sides of the printing numbers
    triangle() # calling the function
    

    would print something like this

                           1
                    1              1
               1           2            1
          1         3            3            1
      1        4        6            4               1
    
    0 讨论(0)
  • 2020-11-30 06:44

    Here is my attempt:

    def generate_pascal_triangle(rows):
        if rows == 1: return [[1]]
    
        triangle = [[1], [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 = [1] + [sum(column) for column in zip(row[1:], row)] + [1]
            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
    0 讨论(0)
提交回复
热议问题