Bon, pour les maux de tête, rien de tel qu'une bonne nuit de sommeil...
J'espère que tout le monde a bien dormi, car encore des coderies :
J'obtiens les résultats en un peu moins de 16 secondes sur TI-74 avec le code suivant :
Code : Tout sélectionner
5 DIM D(2,9)
10 FOR I=1 TO 9:C=I*I*I:D(0,I)=(C-I)/6:D(1,I)=(10*I-C)/6
20 D(2,I)=15*I+D(1,I):NEXT I:S$=""
30 M=D(2,A)+D(1,B):IF ABS(M)=INT(M) THEN C=INT(2*M^.32) ELSE 60
40 IF M=D(0,C)THEN PRINT S$;A;B;C;:S$=" & ";:IF C=0 THEN PRINT S$;A;B;1;
50 IF M>0 AND B<8 THEN B=B+2:GOTO 30
60 IF A<9 THEN A=A+1:P=1-P:B=P:GOTO 30
70 PRINT ".":PAUSE :END
Et l'affichage final:
Qui ressemble très fortement à cette version pour QBASIC:
Code : Tout sélectionner
5 DIM D(2,9) AS SINGLE
DEFINT A-C, I, P
DEFSNG M
DEFSTR S$
REM ====== Initialisation
10 FOR I=1 TO 9
: C=I*I*I : D(0,I)=(C-I)/6 : D(1,I)=(10*I-C)/6
: D(2,I)=15*I+D(1,I)
NEXT I : S$="" : P=0
REM ====== Boucle de Recherche
20 FOR A=0 TO 9
: FOR B=P TO 9 STEP 2
30 : : M=D(2,A)+D(1,B)
: : IF ABS(M)=INT(M) THEN C=INT(2*M^.32) ELSE EXIT FOR
40 : : IF M=D(0,C) THEN PRINT S$;A;B;C; : S$=" & "; : IF C=0 THEN PRINT S$;A;B;1;
50 : NEXT B : P=1-P
60 NEXT A
REM ====== Finalisation Affichage
PRINT "." : END
Comme quoi je pense que le code pour TI-74 peut être encore optimiser.
Et la codderie pour machine RPL :
Là peut-être qu'il ne va falloir analyse cela que cet après-midi après une bonne sieste :
J'ai imaginé le code suivant et je donne à droite les raisons de ne pas l'utiliser pour un MPO
Code : Tout sélectionner
« { } // Initialise la liste qui contiendra les résultats
0 9 FOR a // x10 Boucles sur a
0 9 FOR b // x100 Boucles sur b
0 9 FOR c // x1000 Boucles sur c
100 a * 10 b * c + + // Calcul de n=abc 2000x multiplications et additions
a a a * * b b b * * c c c * * + + // Calcul de s=a3+b3+c3 6000x multiplications et 2000 additions de plus
IF OVER == THEN + ELSE DROP END // Plus de 1000 tests pour au total ajouter au plus 6 entiers à la liste
NEXT // Boucle sur c (mais une seule solution existe à chaque b sauf pour c=0)
NEXT // Boucle sur b pair et impair independemment de parité de a
NEXT // Boucle sur a
» // Retune la liste résultat { 0 1 153 370 371 407 } après environ 2 min.
2 min c'est pas mal pour exécuter presque 40000 instructions dont 8000 multiplications et 4000 additions.
Cela fait une moyenne de ~330 commandes par seconde.
On peut diviser par deux le temps d'exécution en évitant de répéter systématiquemetn les calculs :
Comme le RPL permet de manipuler des couples (a,b), les fonctions de gestion des complexes R->C et C->R sont utilisées pour limiter les manipulations de la pile. Ce qui permet de n'utiliser qu'un seul niveau de pile pour mémoriser les valeurs des somme aprtielles n et s.
Code : Tout sélectionner
« { } // Initialise la liste qui contiendra les résultats
0 9 FOR a // x10 Boucles sur a
100 a * a a a * * R->C // Calcul de na et sa que l'on laisse dans la pile sous form de couple (na,sa)
0 9 FOR b // x100 Boucles sur b
10 b * b b b * * R->C // Calcul de nb et sb
OVER + // Calcul de na+nb et sa+sb que l'on laisse dans la pile (na+nb,sa+sb)
0 9 FOR c // x1000 Boucles sur c
c c c c * * R->C // Calcul de nc et N-S
OVER + // Calcul de N S qui fait 2330x multiplications et 1100 additions 2110 réarrangements R->C/C->R
C->R // On remet N et S dans la pile
IF OVER == // Les mêmes 1000 tests pour ajouter les 6 entiers solution à la liste
THEN 4 ROLL + ROT ROT // Ajoute n à la liste des résultats totu en préservant (na,sa) et (na+nb,sa+sb)
ELSE DROP END
NEXT // Boucle sur c (mais une seule solution existe à chaque b sauf pour c=0)
DROP // Efface (na+nb,sa+sb) devenu obsolète
NEXT // Boucle sur b pair et impair independemment de parité de a
DROP // Efface (na,sa) devenu obsolette
NEXT // Boucle sur a
» // Retune la liste résultat { 407 371 370 153 1 0 } après 1 min 10s
On peut encore économiser du temps en ne parcourrant pas toute les valeurs de b mais uniquement celles correspondant à la parité de a.
Code : Tout sélectionner
« DEG { } // Initialise la liste qui contiendra les résultats
0 9 FOR a // x10 Boucles sur a
100 a * a a a * * R->C // Calcul de na et sa que l'on laisse dans la pile sous form de couple (na,sa)
a 2 MOD 9 FOR b // x50 Boucles sur b
10 b * b b b * * R->C // Calcul de nb et sb
OVER + // Calcul de na+nb et sa+sb que l'on laisse dans la pile (na+nb,sa+sb)
0 9 FOR c // x500 Boucles sur c
c c c c * * R->C // Calcul de nc et N-S
OVER + // Calcul de N S qui fait 680x multiplications et 550 additions 1050 réarrangements R->C/C->R
IF ARG 45 == // Test modifié qui évite un réarrangement tests
THEN ROT a b c ->ARRY + ROT ROT END // x6 Ajoute [abc] à la liste des résultats
NEXT // Boucle sur c (mais une seule solution existe à chaque b sauf pour c=0)
DROP // Efface (na+nb,sa+sb) devenu obsolète
2 STEP // Boucle sur b pair et impair independemment de parité de a
DROP // Efface (na,sa) devenu obsolette
NEXT // Boucle sur a
» // Returne la liste résultat après environ 49s
Reste que la partie qui fait le plus économiser et de supprimer la boucle intérieure en estimant pour chaque couple (a,b)une valeur de c que l'on teste:
Code : Tout sélectionner
« { } // Initialise la liste qui contiendra les résultats
0 9 FOR a // x10 Boucles sur a
100 a * a 3 ^ R->C // Calcul de da=na-sa que l'on laisse dans la pile
a 2 MOD 9 FOR b // x50 Boucles sur b
10 b * b 3 ^ R->C // Calcul de db=nb-sb que l'on laisse dans la pile
OVER + C->R OVER - NEG 6 / // Calcul du sixième de la difèrence M=(da+db)/6= (na+nb-sa-db)/6
IF DUP ABS OVER IP == THEN // Test combiné de signe et de mltiplicité
DUP .32 ^ 2 * FLOOR -> n m c // x500 Calcul estimation de c = FLOOR(2.M^.32)
« IF m 6 * c + c 3 ^ == THEN // Test que c estimé est effectivement une solution
SWAP n c + + // Ajoute la solution n+c à la liste
IF c NOT THEN n 1 + + END // Ainsi que la solution n+1 lorsque c==0
SWAP 999 // Sort de la boucle FOR b - une seule solution possible pour chaque couple a,b
ELSE 2 END » // Si c n'est pas solution, cherche le b suivant
ELSE DROP2 999 END // A défaut de commande ABORT ou EXIT FOR un 999 STEP fera l'affaire ici
STEP DROP // Boucle sur b pair et impair independemment de parité de a // Efface da=na-sa devenu obsolette
NEXT // Boucle sur a
» // Returne la liste résultat { 0 1 153 370 371 407 } après 10s
Le gain de temps est appréciable, les calculs compliqués ne se faisant que de temps en temps, c'est à dire lorsque la somme partielle est multiple de 6.
Les valeurs b parcourrues sont celle correspondant à la parité de a et de plus, on sort de la boucle dès que les sommes partielle sont négatives. Les cubes croissants plus rapidement que les valeurs linéaires issues de b,
On peut diminuer ce temps avec un code à peine plus compliqué : La fonction DOT est utilisée pour calculer la valeur de l'entier à partir du triplet [a b c]. Ce qui évite d'avoir à manipuler les sommes parcielles et donc instruction des nombres complexes.
Code : Tout sélectionner
« { } // Initialise la liste qui contiendra les résultats
0 9 FOR a // x10 Boucles sur a
'Dat58' 21 a + GET // Calcul de da=na-sa à partir de ma matrice pré-calculée
a 2 MOD 9 FOR b // x50 Boucles sur b
'Dat58' 11 b + GET // Calcul de db=nb-sb à partir de la matrice Dat58
OVER + // Calcul du sixième de la difèrence M=(da+db)/6
IF DUP ABS OVER IP == THEN // Test combiné de signe et de mltiplicité
DUP .32 ^ 2 * FLOOR -> c // Calcul estimation de c = FLOOR(2.M^.32)
« IF 6 * 'Dat58' 1 c + GET == THEN // Test que c estimé est effectivement une solution
SWAP a b c 3 ->ARRY [100 10 1] DOT // x6 Ajoute la solution n+c à la liste
IF c NOT THEN DUP 1 + {} + + END // Ainsi que la solution n+1 lorsque c==0
+ SWAP 999 // Sort de la boucle FOR b (il n'y a qu'une solution
ELSE 2 END » // Si c n'est pas solution, cherche le b suivant
ELSE DROP 999 END // A défaut de commande ABORT ou EXIT FOR un 999 STEP fera l'affaire ici sortir
STEP DROP // Boucle sur b pair et impair independemment de parité de a
// Efface da=na-sa devenu obsolette
NEXT // Boucle sur a
» // Returne la liste résultat { 0 1 153 370 371 407 } après 8s
DAT58: // Matrice prè-calculée contenant les sixièmes des diffèrences partielles
[[ 0 0 1 4 10 20 35 56 84 120 ]
[ 0 1.5 2 .5 -4 -12.5 -26 -45.5 -72 -106.5]
[ 0 16.5 32 45.5 56 62.5 64 59.5 48 +28.5]]
Le gain de temps provient que cette fois on ne réalise qu'une centaine d'addition et deux centaines de multiplications, autant de calcul de puissance , en comptant celles nécessaire à la création des 3à éléments de la matrice 'Dat58'
Ce qui fait, que malgré la gestion plus sophistiqué de la pile, on gangne du temps surtout que en évitant la répétition des calculs identique lors de la répétition des boucles FOR b