2

Je travaille sur un code qui créera un triangle visuel de Sierpinski en 3D, et pour que cela fonctionne, je dois utiliser un algorithme de Pascal Pascal qui va créer un tableau afin que je puisse utiliser mon algorithme pour créer mes triangles où ne pas mettre des triangles. Quoi qu'il en soit, le problème est que mon code qui arrange les triangles crée les triangles par colonne plutôt que par ligne comme le fait l'algorithme de Pascal, donc j'essaie juste de faire une solution rapide en ayant un sous-programme qui réorganise le tableau Pascal. Je suis juste perplexe sur la façon de le faire depuis je ne sais pas comment éviter les erreurs index out of range.Comment changer de ligne et de colonne dans un tableau 2D?

Ceci est le code qui crée le tableau pour le triangle de Pascal.

TL: DR Je suis en train de faire un Réorganiser un tableau où les lignes sont les colonnes et les colonnes sont les lignes

def pascal(n): 
    """Prints out n rows of Pascal's triangle.""" 
    row = [1] 
    global array 
    array = [[0 for x in range(int(n))] for y in range(int(n))] 
    array[0]=row 
    k = [0] 
    for x in range(int(max(n,0)-1)): 
     row=[l+r for l,r in zip(row+k,k+row)] 
     array[x+1]=row 
    return 1 

Ceci est la sortie de l'impression du tableau. Je veux juste les lignes à colonnes et des colonnes pour être rangées

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

Voici le code complet si vous êtes curieux au sujet du projet, mais il faut rhinoscriptsyntax de rendre le modèle.

import rhinoscriptsyntax as rhino 
import math 

obj = rhino.GetObject("Select object to transform", preselect=True) 
scale = 3 
n=math.pow(3,scale) 
def pascal(n): 
    """Prints out n rows of Pascal's triangle.""" 
    row = [1] 
    global array 
    array = [[0 for x in range(int(n))] for y in range(int(n))] 
    array[0]=row 
    k = [0] 
    for x in range(int(max(n,0)-1)): 
     row=[l+r for l,r in zip(row+k,k+row)] 
     array[x+1]=row 
    return 1 
pascal(math.pow(2,scale)) 
print array 
def remakePascal(): 
    pass 
my_horizontalVector = [[1,0,0,6], 
      [0,1,0,0], 
      [0,0,1,0], 
      [0,0,0,1]] 

my_tsfm = [[1,0,0,0], #identity 
      [0,1,0,0], 
      [0,0,1,0], 
      [0,0,0,1]] 


def makeTriangle(scale,obj): 
    w=1/scale 
    h=1/scale 
    tsfm= [[w,0,0,0], #scale about origin 
      [0,h,0,0], 
      [0,0,1,0], 
      [0,0,0,1]] 
    output= rhino.XformMultiply(my_tsfm,tsfm) 
    new_obj=rhino.TransformObject(obj,output,copy=True) 
    return new_obj 
def placeObj(i): 
    my_moveUpVector = [[1,0,0,(3/scale)*i], 
      [0,1,0,(4/scale)*i], 
      [0,0,1,0], 
      [0,0,0,1]] 
    vector = rhino.XformMultiply(my_tsfm,my_moveUpVector) 
    return vector 
n=0 
for i in range(int(math.pow(2,scale))): 
    if(i>0): 
     hPlace=rhino.XformMultiply(my_tsfm,my_horizontalVector) 
     obj = rhino.TransformObject(obj,hPlace) 
    factor = int(math.pow(2,scale))-n 
    for j in range(factor): 
     if(): 
      pass 
     else: 
      Vertobj=makeTriangle(scale,obj) 
      tsfm = rhino.TransformObject(Vertobj,placeObj(j),copy=True) 
    n=n+1 

Répondre

1

Vous pouvez le faire comme indiqué. Cela fonctionne en faisant d'abord le carré du tableau afin que toutes les lignes aient le même nombre d'éléments. Transpose ensuite les lignes et les colonnes à l'aide de la fonction zip() intégrée, puis supprime les éléments initialement ajoutés.

Notez également que j'ai supprimé l'utilisation de la variable globale array. Les variables globales sont mieux évitées.

from pprint import pprint 

def pascal(n): 
    """Creates n rows of Pascal's triangle.""" 
    array = [None for y in range(n)] 

    row = [1] 
    array[0] = row 
    k = [0] 
    for x in range(max(n, 0)-1): 
     row = [l+r for l,r in zip(row+k, k+row)] 
     array[x+1] = row 

    return array 

def transpose(array): 
    array = array[:] # make copy to avoid changing original 
    n = len(array) 
    for i, row in enumerate(array): 
     array[i] = row + [None for _ in range(n - len(row))] 

    array = zip(*array) 

    for i, row in enumerate(array): 
     array[i] = [elem for elem in row if elem is not None] 

    return array 

array = pascal(8) 
array = transpose(array) 
pprint(array) 

sortie:

[[1, 1, 1, 1, 1, 1, 1, 1], 
[1, 2, 3, 4, 5, 6, 7], 
[1, 3, 6, 10, 15, 21], 
[1, 4, 10, 20, 35], 
[1, 5, 15, 35], 
[1, 6, 21], 
[1, 7], 
[1]] 
+0

I ne pouvait pas dire si votre compréhension de la liste de transposition était du sudocode ou du code réel. Je suis assez nouveau pour Python, donc j'ai dû le chercher, mais merci pour l'aide maintenant je peux avoir une représentation réelle d'un triangle Sierpinski. – Dayman

+0

Dayman: Non, pas de pseudo-code, juste le _Real Thing_ ™. ';-)' – martineau

1

Vous voulez probablement quelque chose comme ceci:

def pascal(n): 
    a = [[int(i==0) for j in range(n)] for i in range(n)] 
    for i in range(n): 
     for j in range(1, 1+i): 
      a[j][i] = a[j][i-1] + a[j-1][i-1] 

    for line in a: print(line) 

pascal(7) 

cette impression:

[1, 1, 1, 1, 1, 1, 1] 
[0, 1, 2, 3, 4, 5, 6] 
[0, 0, 1, 3, 6, 10, 15] 
[0, 0, 0, 1, 4, 10, 20] 
[0, 0, 0, 0, 1, 5, 15] 
[0, 0, 0, 0, 0, 1, 6] 
[0, 0, 0, 0, 0, 0, 1] 
3

Pour transposer les tableaux carrés, la solution est simple

transposed_array = zip(*array) 

Cette approche est Pas adapté pour Les données triangulaires zip n'insèrent pas de remplissage lorsque les lignes sont de longueur inégale. itertools.izip_longest le fait, cependant:

import itertools 
transposed_array = itertools.izip_longest(*array) 

par des tampons par défaut izip_longest avec None, donc vous obtenez des résultats tels que:

[(1, 1, 1, 1, 1), 
(None, 1, 2, 3, 4), 
(None, None, 1, 3, 6), 
(None, None, None, 1, 4), 
(None, None, None, None, 1)] 

Si vous le souhaitez, vous pouvez supprimer les None entrées avec une compréhension de la liste:

no_nones = [[item for item in row if item is not None] for row in transposed_array] 

qui vous laisse avec:

[[1, 1, 1, 1, 1], 
[1, 2, 3, 4], 
[1, 3, 6], 
[1, 4], 
[1]] 

Si vous préférez remplir avec 0 (ou toute autre chose), spécifiez que l'argument mot-clé fillvalue à itertools.izip_longest; par exemple.

list(itertools.izip_longest(*array, fillvalue=0)) 

retours

[(1, 1, 1, 1, 1), 
(0, 1, 2, 3, 4), 
(0, 0, 1, 3, 6), 
(0, 0, 0, 1, 4), 
(0, 0, 0, 0, 1)] 

je présume ici qu'une liste de tuples fonctionne à vos besoins. Si vous avez besoin de l'intérieur pour mutable, vous pouvez obtenir cela avec une compréhension de liste, par ex.:

list_of_lists = [list(row) for row in transposed_array] 
+0

Alors puis-je imprimer simplement 'transposed_array' comme tout autre tableau en utilisant' imprimer transposed_array'? – Dayman

+2

Oui, vous pouvez. Si vous voulez obtenir la liste de la liste (pas la liste de tuple), vous pouvez écrire ceci en une ligne: 'list_of_lists = list (map (liste, itertools.izip_longest (* tableau, fillvalue = 0)))' – ADR

0

Vous pouvez transposer les lignes et les colonnes après chaque longueur correspondant à des lignes avec des rangées max et le remplissage avec des zéros.

Code de travail comme ci-dessous. numpy_fillna fonction provenant de this SO post.

import numpy as np 
x = [[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]] 

a = np.array(x) 

def numpy_fillna(data): 
    # Get lengths of each row of data 
    lens = np.array([len(i) for i in data]) 

    # Mask of valid places in each row 
    mask = np.arange(lens.max()) < lens[:,None] 

    # Setup output array and put elements from data into masked positions 
    out = np.zeros(mask.shape, dtype=data.dtype) 
    out[mask] = np.concatenate(data) 
    return out 

Résultat

>>> numpy_fillna(a).T 
array([[1, 1, 1, 1, 1, 1, 1, 1], 
     [0, 1, 2, 3, 4, 5, 6, 7], 
     [0, 0, 1, 3, 6, 10, 15, 21], 
     [0, 0, 0, 1, 4, 10, 20, 35], 
     [0, 0, 0, 0, 1, 5, 15, 35], 
     [0, 0, 0, 0, 0, 1, 6, 21], 
     [0, 0, 0, 0, 0, 0, 1, 7], 
     [0, 0, 0, 0, 0, 0, 0, 1]], dtype=object) 
>>>