J'ajoute cela comme une deuxième réponse puisqu'elle est dans une langue différente (maintenant C) et a une approche plus directe. Je garde la réponse originale puisque le code suivant est presque inexplicable sans cela. J'ai combiné mes deux fonctions en une seule pour réduire les frais généraux d'appel de fonction. Aussi, pour être sûr à 100% qu'il répond à la question initiale, j'ai utilisé textuellement les boucles de cette question. Dans la fonction pilote, je montre explicitement que la sortie est correcte pour N = 4, puis je la soumets à un test de contrainte pour N = 10000 (avec un total de 100 000 000 passages dans la boucle interne). Je n'ai pas de code temporel officiel, mais il faut environ 1 seconde sur ma machine pour tester et tester ces 100 millions de cas. Mon code suppose un int
32 bits. Changer de long
si nécessaire:
#include <stdio.h>
#include <math.h>
void from_index(int n, int index, int *i, int *j);
int main(void){
int N;
int ri,rj; //recovered i,j
N = 4;
int index = 0;
for (int i = 0; i < N; ++i)
for (int j = 0; j < N-i; ++j){
from_index(N,index,&ri,&rj);
printf("i = %d, j = %d, index = %d, ",i,j,index);
printf("recovered i = %d, recovered j = %d\n",ri,rj);
index++;
}
//stress test:
N = 10000;
index = 0;
for (int i = 0; i < N; ++i)
for (int j = 0; j < N-i; ++j){
from_index(N,index,&ri,&rj);
if(i != ri || j != rj){
printf("Don't post buggy code to Stack Overflow!\n");
printf("(i,j) = (%d,%d) but recovered indices are (%d,%d)\n",i,j,ri,rj);
return 0;
}
index++;
}
printf("\nAll %d tests passed!\n",N*N);
return 0;
}
void from_index(int n, int index, int *i, int *j){
double d;
d = 4*n*(n+1) - 7 - 8 * index;
*i = floor((-1 + sqrt(d))/2);
*j = *i * (*i + 1)/2;
*j = n*(n+1)/2 - 1 - index - *j;
*j = *i - *j;
*i = n - *i - 1;
}
Sortie:
i = 0, j = 0, index = 0, recovered i = 0, recovered j = 0
i = 0, j = 1, index = 1, recovered i = 0, recovered j = 1
i = 0, j = 2, index = 2, recovered i = 0, recovered j = 2
i = 0, j = 3, index = 3, recovered i = 0, recovered j = 3
i = 1, j = 0, index = 4, recovered i = 1, recovered j = 0
i = 1, j = 1, index = 5, recovered i = 1, recovered j = 1
i = 1, j = 2, index = 6, recovered i = 1, recovered j = 2
i = 2, j = 0, index = 7, recovered i = 2, recovered j = 0
i = 2, j = 1, index = 8, recovered i = 2, recovered j = 1
i = 3, j = 0, index = 9, recovered i = 3, recovered j = 0
All 100000000 tests passed!
vous dire comme quotient et le reste? –
@JohnColeman Ceci est légèrement plus difficile que cela en raison de la limite supérieure variable de la boucle interne. Mais la réponse est "oui, c'est possible". Dans le pire des cas, vous pouvez rejouer les deux boucles et casser quand vous atteignez la valeur de l'index: p Mais, vous pouvez probablement le faire en temps constant, en résolvant une ou plusieurs équations quadratiques. – cobarzan
J'ai raté ce 'i'. Probablement besoin d'utiliser le fait que 1 + 2 + 3 + ... + n = n (n + 1)/2. Un peu d'algèbre semble être nécessaire au lieu de la théorie des nombres droits. Je vote la question comme étant à la fois intéressante et pas très triviale. –