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.
我工作在一个代码将创建一个视觉Sierpinski三角形的3 d打印,为了工作我必须使用帕斯卡三角形算法,将创建一个数组,所以我可以使用它来告诉我的算法,将创建三角形不把三角形。
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.
不管怎样,问题是,我用来排列三角形的代码是按列创建三角形而不是按行创建的就像Pascal算法那样我只是想通过一个重新排列Pascal数组的子例程来做一个快速修复。由于我不知道如何避免索引超出范围的错误,所以我对如何做这个问题感到困惑。
This is the code that creates the array for Pascal's triangle.
这是为Pascal三角形创建数组的代码。
TL:DR I am trying to make an rearrange an array where rows are the columns and columns are the rows
TL:DR我正在尝试重新排列一个数组,其中行是列,列是行
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.
如果您对这个项目感到好奇,那么这里是完整的代码,但是它需要使用rhinoscriptsyntax来创建模型。
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
4 个解决方案
#1
1
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.
你可以像展示的那样做。它的工作方式是首先将数组平方,这样所有的行都有相同数量的元素。然后使用内置的zip()函数替换行和列,最后删除它最初添加的元素。
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]]
#2
3
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:
这种方法不适用于三角形数据,因为当行长度不相等时,zip不会插入填充。itertools。然而,izip_longest做:
import itertools
transposed_array = itertools.izip_longest(*array)
By default izip_longest
pads with None
, so you get results like:
默认情况下,izip_最长的pad没有,所以你会得到如下结果:
[(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.
如果您喜欢使用0(或其他)填充,请指定为itertools.izip_longest的fillvalue关键字参数;如。
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]
#3
1
You probably want something like this:
你可能想要这样的东西:
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)
this prints:
这个打印:
[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]
#4
0
You can transpose the rows and columns after matching length of each rows with max row and filling with zeros.
您可以在每一行的长度与max行匹配并填充0之后转置行和列。
Working code as below. numpy_fillna
function sourced from this SO post.
工作代码如下。numpy_fillna函数来源于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
Result
结果
>>> 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)
>>>
#1
1
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.
你可以像展示的那样做。它的工作方式是首先将数组平方,这样所有的行都有相同数量的元素。然后使用内置的zip()函数替换行和列,最后删除它最初添加的元素。
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]]
#2
3
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:
这种方法不适用于三角形数据,因为当行长度不相等时,zip不会插入填充。itertools。然而,izip_longest做:
import itertools
transposed_array = itertools.izip_longest(*array)
By default izip_longest
pads with None
, so you get results like:
默认情况下,izip_最长的pad没有,所以你会得到如下结果:
[(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.
如果您喜欢使用0(或其他)填充,请指定为itertools.izip_longest的fillvalue关键字参数;如。
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]
#3
1
You probably want something like this:
你可能想要这样的东西:
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)
this prints:
这个打印:
[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]
#4
0
You can transpose the rows and columns after matching length of each rows with max row and filling with zeros.
您可以在每一行的长度与max行匹配并填充0之后转置行和列。
Working code as below. numpy_fillna
function sourced from this SO post.
工作代码如下。numpy_fillna函数来源于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
Result
结果
>>> 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)
>>>