[编辑:第四次的魅力,终于有点明智]
我倒退了:我从另一个显示基于过滤器的方法的答案开始,并用它来生成一系列值的所有有效组合n,并在在线整数序列数据库中查找序列。组合数为n2(n2+3),这看起来不太可能(为什么是 3?)。也是t(t(n))+t(t(n−1))在哪里t(a)是三角数a,t(a)=a(a+1)/2. 有了这个,我们需要知道为什么。
第一项更简单 - 对i≥j和tid(i,j)≥tid(k,l), 在哪里tid(a,b)是三角指数a,b. 这是通过这样的功能实现的:
def ascendings(n):
idx = 0
for i in range(1,n+1):
for j in range(1,i+1):
for k in range(1,i):
for l in range(1,k+1):
idx = idx + 1
print(i,j,k,l)
k=i
for l in range(1,j+1):
idx = idx + 1
print(i,j,k,l)
return idx
第二个在哪里l循环是因为我们不能嵌套l完全在里面循环k没有 if/skip 的循环来检查三角形索引。
第二学期t(t(n−1))是第一对上升,第二对下降的地方(注意,没有==,因为它们在上面处理过)。
def mixcendings(n):
idx = 0
for j in range(2,n+1):
for i in range(1,j):
for k in range(1,j):
for l in range(1,k):
print(i,j,k,l)
idx = idx + 1
k=j
for l in range(1,i+1):
print(i,j,k,l)
idx = idx + 1
return idx
这两者的组合给出了完整的集合,因此将两个循环放在一起给出了完整的索引集合。
一个重要的问题是,对于任意 i,j,k,l,这些模式很难计算。所以我会建议一张地图,它产生给定 i,j,k,l 的索引。坦率地说,如果您要这样做,您不妨使用 generate+filter 方法,因为您只需要对给定的情况执行一次n. 上述方法的好处是你至少有一个可预测的循环结构。
在 python 中,我们可以编写以下迭代器来为我们提供每个不同场景的 idx 和 i,j,k,l 值:
def iterate_quad(n):
idx = 0
for i in range(1,n+1):
for j in range(1,i+1):
for k in range(1,i):
for l in range(1,k+1):
idx = idx + 1
yield (idx,i,j,k,l)
#print(i,j,k,l)
k=i
for l in range(1,j+1):
idx = idx + 1
yield (idx,i,j,k,l)
for i in range(2,n+1):
for j in range(1,i):
for k in range(1,i):
for l in range(1,k):
idx = idx + 1
yield (idx,i,j,k,l)
k=i
for l in range(1,j+1):
idx = idx + 1
yield (idx,i,j,k,l)
在 fortran 中,我们只需要运行循环并存储值。我们可以使用一个简单的索引将 i,j,k,l 组合存储为单个值 (in3+jn2+kn+l),并将这些值存储在索引与上述索引相同的数组中。然后我们可以遍历这个数组并从值中检索 i,j,k,l。要获得任意 i,j,k,l 的 idx,需要一个反向映射和一个过滤器来处理对称性,尽管我们可能可以从上述结构构造一个函数。fortran 中的 idx 数组生成函数为:
integer function squareindex(i,j,k,l,n)
integer,intent(in)::i,j,k,l,n
squareindex = (((i-1)*n + (j-1))*n + (k-1))*n + l
end function
integer function generate_order_array(n,arr)
integer,intent(in)::n,arr(*)
integer::total,idx,i,j,k,l
total = n**2 * (n**2 + 3)
reshape(arr,total)
idx = 0
do i=1,n
do j=1,i
do k=1,i-1
do l=1,k
idx = idx+1
arr(idx) = squareindex(i,j,k,l,n)
end do
end do
k=i
do l=1,j
idx = idx+1
arr(idx) = squareindex(i,j,k,l,n)
end do
end do
end do
do i=2,n
do j=1,i-1
do k=1,i-1
do l=1,j
idx = idx+1
arr(idx) = squareindex(i,j,k,l,n)
end do
end do
k=i
do l=1,j
idx = idx+1
arr(idx) = squareindex(i,j,k,l,n)
end do
end do
end do
generate_order_array = idx
end function
然后循环遍历它:
maxidx = generate_order_array(n,arr)
do idx=1,maxidx
i = idx/(n**3) + 1
t_idx = idx - (i-1)*n**3
j = t_idx/(n**2) + 1
t_idx = t_idx - (j-1)*n**2
k = t_idx/n + 1
t_idx = t_idx - (k-1)*n
l = t_idx
! now have i,j,k,l, so do stuff
! ...
end do