Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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
like image 460
Dayman Avatar asked Apr 02 '17 02:04

Dayman


1 Answers

For transposing square arrays, the simple solution is

transposed_array = zip(*array)

This approach is not suitable for triangular data as zip does not insert padding when the rows are of unequal length. itertools.izip_longest does, however:

import itertools
transposed_array = itertools.izip_longest(*array)

By default izip_longest pads with None, so you get results like:

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

If you wish, you can remove the None entries with a list comprehension:

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

which leaves you with:

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

If you prefer to pad with 0s (or anything else), specify that as the fillvalue keyword argument to itertools.izip_longest; e.g.

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

returns

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

I'm assuming here that a list of tuples works for your purposes. If you need the inside to mutable, you can get that with a list comprehension, e.g.:

list_of_lists = [list(row) for row in transposed_array]
like image 59
ramcdougal Avatar answered Sep 21 '22 15:09

ramcdougal