[Editar: cuarta vez es el encanto, por fin algo sensato]
Llegué a esto al revés: comencé con otra respuesta que mostraba el enfoque basado en filtros, y usé eso para generar todas las combinaciones válidas para una serie de valores de , y busqué la secuencia en la base de datos de secuencias de enteros en línea. El número de combinaciones es , lo que parece poco probable (¿por qué el 3?). También es donde es el número triangular de , . Habiendo entendido esto, necesitamos saber por qué.nn2(n2+3)t(t(n))+t(t(n−1))t(a)at(a)=a(a+1)/2
El primer término es más simple: los pares de pares donde y , donde es el índice triangular de . Eso se cumple con una función como esta:t i d ( i , j ) ≥ t i d ( k , l ) t i d ( a , b ) a , bi≥jtid(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
donde el segundo bucle es porque no podemos anidar el bucle completo dentro del bucle sin un if / skip para verificar los índices triangulares.l kllk
El segundo término es donde el primer par es ascendente y el segundo par es descendente (nota, no ==, como se manejan arriba).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
La combinación de ambos proporciona el conjunto completo, por lo que al unir ambos bucles se obtiene el conjunto completo de índices.
Un problema importante es que estos patrones son difíciles de calcular para un arbitrario i, j, k, l. Por lo tanto, sugeriría un mapa que arroje el índice dado i, j, k, l. Francamente, si está haciendo esto, también podría usar el enfoque de generar + filtro, porque solo necesita hacerlo una vez para un dado . El lado positivo del método anterior es que al menos tiene una estructura de bucle predecible.n
En python podemos escribir el siguiente iterador para darnos los valores idx e i, j, k, l para cada escenario diferente:
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)
En fortran solo tendríamos que ejecutar el ciclo y almacenar los valores. Podemos usar un índice simple para almacenar la combinación i, j, k, l como un valor único ( ), y almacenar estos valores en una matriz cuyo índice es el mismo que el índice encima. Luego podemos iterar sobre esta matriz y recuperar i, j, k, l de los valores. Para obtener el idx para i, j, k, l arbitrario, se requeriría un mapa inverso y un filtro para manejar la simetría, aunque probablemente podríamos construir una función a partir de la estructura anterior. La función de generación de matriz idx en fortran sería:in3+jn2+kn+l
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
Y luego repítelo así:
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