web-dev-qa-db-fra.com

Le triangle de Pascal pour Python

En tant qu’apprentissage pour Python, j’essaie de coder ma propre version du triangle de Pascal. Cela m'a pris quelques heures (comme je viens de commencer), mais je suis sorti avec ce code:

pascals_triangle = []

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

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

pascals_tri_gen(6)

for row in pascals_triangle:
    print(row)

qui retourne

[1]
[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]

Cependant, je ne sais pas où aller à partir de maintenant. Je frappe ma tête contre le mur depuis des heures. Je tiens à souligner que je ne veux pas que vous le fassiez pour moi; Poussez-moi dans la bonne direction. En tant que liste, mon code retourne

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

Merci.

EDIT: J'ai pris quelques bons conseils et j'ai complètement réécrit mon code, mais je rencontre maintenant un autre problème. Voici mon 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)

Cependant, je constate que la sortie est un peu indésirable:

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

Comment puis-je réparer cela?

11
louie mcconnell

Examen du code OK:

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)

impressions:

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

Explication du triangle de Pascal:

C'est la formule pour "n choisissez k" (c'est-à-dire combien de manières différentes (sans tenir compte de l'ordre), à ​​partir d'une liste ordonnée de n éléments, pouvons-nous choisir k éléments):

from math import factorial

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

Un intervenant a demandé si cela était lié à itertools.combinations - en effet, "n choisissez k" peut être calculé en prenant la longueur d'une liste d'éléments de combinaisons:

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

Voyons cela démontré:

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]]

Nous pouvons éviter de nous répéter avec une compréhension de liste imbriquée:

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]]

Défini récursivement:

Nous pouvons définir cela récursivement (une définition moins efficace, mais peut-être plus élégante mathématiquement) en utilisant les relations illustrées par le 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)

Et pour le plaisir, vous pouvez voir que chaque ligne est de plus en plus longue à s'exécuter, car chaque ligne doit recalculer presque chaque élément de la ligne précédente deux fois:

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 pour arrêter quand vous êtes fatigué de le regarder, ça devient très lent, très vite ...

14
Aaron Hall

Je sais que vous souhaitez implémenter vous-même, mais la meilleure façon de l'expliquer consiste à effectuer une implémentation. Voici comment je le ferais, et cette implémentation repose sur ma connaissance assez complète du fonctionnement des fonctions de Python. Par conséquent, vous ne voudrez probablement pas utiliser ce code vous-même, mais cela peut vous orienter dans la bonne direction.

def pascals_triangle(n_rows):
    results = [] # a container to collect the rows
    for _ in range(n_rows): 
        row = [1] # 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]
[1, 2, 1]
[1, 3, 3, 1]
[1, 4, 6, 4, 1]
[1, 5, 10, 10, 5, 1]
10
Aaron Hall

Sans utiliser Zip, mais en utilisant un générateur: 

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

Exemple: 

print(list(gen(15)))

sortie: 

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

AFFICHER COMME TRIANGLE

Pour le dessiner dans un beau triangle (ne fonctionne que pour n <7, au-delà, il est distrait. Ref draw_beautiful pour n> 7) 

pour n <7 

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

par exemple:

draw(10)

sortie: 

      1       

     1 1      

    1 2 1     

   1 3 3 1    

  1 4 6 4 1   

1 5 10 10 5 1   

pour toute taille

puisque nous avons besoin de connaître la largeur maximale, nous ne pouvons pas utiliser de générateur

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')

exemple (2): fonctionne pour n'importe quel nombre: 

draw_beautiful(100)

 example of n = 100

4
MortalViews

Voici ma tentative:

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

  • Les deux premières lignes du triangle sont codées en dur
  • L’appel Zip() relie essentiellement deux numéros adjacents
  • Il faut encore ajouter 1 au début et un autre à la fin car l'appel Zip() ne génère que le milieu de la ligne suivante
2
Hai Vu
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)
1
Abdel

Voici une solution récursive élégante et efficace. J'utilise la très pratique 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 [1]
    prev_row = pascals_triangle(n-1)
    return [1, *map(sum, sliding_window(2, prev_row)), 1]

pascals_triangle(300) prend environ 15 ms sur un macbook pro (Intel Core i5 à 2,9 GHz). Notez que vous ne pouvez pas aller beaucoup plus haut sans augmenter la limite de profondeur de récursivité par défaut.

1
fredcallaway
# 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

imprimerait quelque chose comme ça 

                       1
                1              1
           1           2            1
      1         3            3            1
  1        4        6            4               1
0
Niamatullah Bakhshi
# 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
ssgam

Je triche à partir de la solution populaire séquence de fibonacci . Pour moi, la mise en œuvre du triangle de Pascal aurait le même concept que celui de fibonacci. Dans Fibonacci, nous utilisons un nombre unique à la fois et nous l'ajoutons au précédent. Dans le triangle de Pascal, utilisez une ligne à la fois et ajoutez-la à la précédente. 

Voici un exemple de code complet:

>>> def Pascal(n):
...     r1, r2 = [1], [1, 1]
...     degree = 1
...     while degree <= n:
...         print(r1)
...         r1, r2 = r2, [1] + [sum(pair) for pair in Zip(r2, r2[1:]) ] + [1]
...         degree += 1

Test

>>> Pascal(3)
[1]
[1, 1]
[1, 2, 1]
>>> Pascal(4)
[1]
[1, 1]
[1, 2, 1]
[1, 3, 3, 1]
>>> Pascal(6)
[1]
[1, 1]
[1, 2, 1]
[1, 3, 3, 1]
[1, 4, 6, 4, 1]
[1, 5, 10, 10, 5, 1]

Note: pour que le résultat soit un générateur, remplacez print(r1) par yield r1

0
Aziz Alto

Etudiant débutant en Python ici. Voici ma tentative, une approche très littérale, utilisant deux boucles For:

Pascal = [[1]]
num = int(input("Number of iterations: "))
print(Pascal[0]) # the very first row
for i in range(1,num+1):
    Pascal.append([1]) # 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])
        # add two adjacent numbers of the row above together
    Pascal[i].append(1) # and cap it with 1
    print(Pascal[i])
0
user3932000