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
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]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With