Search code examples
pythonarraysalgorithmmultidimensional-arraypascals-triangle

How do I switch rows and columns in a 2D array?


I am working on a code that will create a visual Sierpinski triangle to 3D print, and in order for it to work I have to use a Pascal triangle algorithm that will create an array so I can use to tell my algorithm that will create my triangles where not to put triangles.

Anyway the problem is, that my code that arranges the triangles creates the triangles by column instead of by row like the Pascal algorithm does so I am just trying to do a quick fix by having a subroutine that rearranges the Pascal array. I am just stumped on how to do it since I am not sure how to avoid index out of range errors.

This is the code that creates the array for Pascal's triangle.

TL:DR I am trying to make an rearrange an array where rows are the columns and columns are the rows

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

This is the output of printing the array. I just want the rows to be columns and columns to be rows

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

Here is the full code if you are curious about the project, but it requires rhinoscriptsyntax to make the model.

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

Solution

  • You could do it as shown. It works by first making the array square so that all the rows have the same number of elements. then transposes the rows and columns using the built-in zip() function, and then finally removes the elements it initially added.

    Note also I removed the use of the global variable array. Global variables are best avoided.

    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)
    

    Output:

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