Apr?s ma question (d?bile) d'hier soir, voila les principes qui te
permettront de faire tourner ton algo en quelques secondes
je te conseille de suivre les ?tapes et de constater (ou non) les
am?liorations progressivement
- utilise "option explicit" (cela t'obligera ? d?clarer tes variables)
- type tes variables
- tu peux utiliser Application.ScreenUpdating = False (anecdotique ici)
- tu peux utiliser Application.Calculation = xlCalculationManual
(anecdotique ici)
Evitons les calculs inutiles
d?j? on remarque que 9^8 * 3 = 129 140 163 (9 chiffres)
donc tout nombre sup?rieur ? 99900000 ne conviendra pas
donc on fait For i = 10000000 To 99900000
'au lieu de For i = 10000000 To 99999999
Le but du jeu va ?tre de ne pas refaire 100 fois les m?me calculs
on va donc construire un tableau des puissances
Dim precalc(0 To 9) As Long
For i = 0 To 9
precalc(i) = i ^ 8
Next i
Ainsi les calculs de puissance ne seront plus ? refaire, il suffira
d?acc?der au tableau
le
se transforme donc en
If precalc(x(1)) + precalc(x(2))
+ precalc(x(3)) + precalc(x(4))
+ precalc(x(5)) + precalc(x(6))
+ precalc(x(7)) + precalc(x(8)) = i Then
ou encore mieux puisque on peut consid?rer que le
'For j = 1 To 8
' x(j) = Mid(i, j, 1)
'Next j
n'est pas n?cessaire
If precalc(CLng(Mid(i, 1, 1))) + precalc(CLng(Mid(i, 2, 1)))
+ precalc(CLng(Mid(i, 3, 1))) + precalc(CLng(Mid(i, 4, 1)))
+ precalc(CLng(Mid(i, 5, 1))) + precalc(CLng(Mid(i, 6, 1)))
+ precalc(CLng(Mid(i, 7, 1))) + precalc(CLng(Mid(i, 8, 1))) = i Then
l? d?j? on devrait avoir gagn? un petit peu de temsp
mais pas encore assez pour en gagner encore plus on va d?boucler le
descendre ? 30 secondes) mais tu peux gagner encore plus en d?bouclant
plusieurs niveaux
tu constate donc que
quand tu passe de xxx xxx x{0-8} ? xxx xxx x{0-8} + 1
il n'y a qu'un chiffre qui change
Pourquoi alors refaire tout le calcul
on declare plus haut un
dim partialSum as long
et on fait
For i = 10000000 To 99900000 Step 10
partialSum = precalc(CLng(Mid(i, 1, 1))) + precalc(CLng(Mid(i, 2, 1)))
+ precalc(CLng(Mid(i, 3, 1))) + precalc(CLng(Mid(i, 4, 1)))
+ precalc(CLng(Mid(i, 5, 1))) + precalc(CLng(Mid(i, 6, 1)))
+ precalc(CLng(Mid(i, 7, 1)))
If partialSum = i Then
k = k + 1
Cells(k, 1) = i
End If
If partialSum + precalc(1) = i + 1 Then
k = k + 1
Cells(k, 1) = i + 1
End If
If partialSum + precalc(2) = i + 2 Then
k = k + 1
Cells(k, 1) = i + 2
End If
...
...
...
If partialSum + precalc(9) = i + 9 Then
k = k + 1
Cells(k, 1) = i + 9
End If
next i
pour tester 10 nombres, au lieu de faire
10*7 = 70 additions (? la louche)
on ne va en faire que 6 + 9 (+9 (pour les i + x)) = 24 !!!
Bon il y a toujours une grosse perte de temps (pas v?rifier mais presque
sur) sur la partie long=>string=>long, il y a moyen de faire mieux...
Pour pousser presque encore plus on peut envisager
(je ne met pas d'indentation volontairement)
...
Dim sumPartial As Long
Dim number As Long
number = 0
sumPartial = 0
For i8 = 1 To 9
number = number + i8 * 10000000
sumPartial = sumPartial + precalc(i8)
For i7 = 0 To 9
number = number + i7 * 1000000
sumPartial = sumPartial + precalc(i7)
For i6 = 0 To 9
number = number + i6 * 100000
sumPartial = sumPartial + precalc(i6)
For i5 = 0 To 9
number = number + i5 * 10000
sumPartial = sumPartial + precalc(i5)
For i4 = 0 To 9
number = number + i4 * 1000
sumPartial = sumPartial + precalc(i4)
For i3 = 0 To 9
number = number + i3 * 100
sumPartial = sumPartial + precalc(i3)
For i2 = 0 To 9
number = number + i2 * 10
sumPartial = sumPartial + precalc(i2)
For i1 = 0 To 9
number = number + i1
sumPartial = sumPartial + precalc(i1)
If sumPartial = number Then
k = k + 1
Cells(k, 1) = number
End If
number = number - i1
sumPartial = sumPartial - precalc(i1)
Next i1
number = number - i2 * 10
sumPartial = sumPartial - precalc(i2)
Next i2
number = number - i3 * 100
sumPartial = sumPartial - precalc(i3)
Next i3
number = number - i4 * 1000
sumPartial = sumPartial - precalc(i4)
Next i4
number = number - i5 * 10000
sumPartial = sumPartial - precalc(i5)
Next i5
number = number - i6 * 100000
sumPartial = sumPartial - precalc(i6)
Next i6
number = number - i7 * 1000000
sumPartial = sumPartial - precalc(i7)
Next i7
number = number - i8 * 10000000
sumPartial = sumPartial - precalc(i8)
Next i8
...
la ca commence vraiment ? poutrer,
en exercice, je te laisse le soin de d?boucler le for repr?sentant les
unit?s (ce n'est pas excessif et on doit encore bien gagner)
En conclusion, pour aller plus vite il te faudra d'une part identifier
et ?viter les calcules inutiles et identifier et supprimer les calculs
redondants. Il y a surement mati?re ? encore pas mal d'optimisation dans
tout ce qui a ?t? expos? ici.
bcar
Le 25/04/2012 17:35, Tatanka a ?crit :