Armstrong Number
Un entier positif est un nombre d’Armstrong lorsqu’il est égal à la somme de ses chiffres, chacun élevé à la puissance correspondant au nombre de chiffres qu’il comporte. 153 comporte trois chiffres et 1^3 + 5^3 + 3^3 = 153, c’est donc un nombre d’Armstrong. Écris une fonction qui reçoit n et renvoie true s’il s’agit d’un nombre d’Armstrong, et false dans le cas contraire.
Fonction
- ninteger
- l’entier positif à tester
- Renvoieboolean
- vrai lorsque n est égal à la somme de ses chiffres, chacun élevé à la puissance du nombre de chiffres
Contraintes
1 ≤ n ≤ 109
Exemples
- Entrée
- n = 153
- Sortie
- true
- Explication
153a 3 chiffres, donc chaque chiffre est élevé au cube :1 + 125 + 27 = 153. La somme redonne le nombre, donc la réponse esttrue.
- Entrée
- n = 10
- Sortie
- false
- Explication
10a 2 chiffres, donc chaque chiffre est élevé au carré :1 + 0 = 1, ce qui n'est pas10. La réponse estfalse.
- Entrée
- n = 9474
- Sortie
- true
- Explication
- Avec 4 chiffres, la puissance est 4 :
6561 + 256 + 2401 + 256 = 9474, le nombre lui-même, donc la réponse esttrue.
Pour aller plus loin
Seuls 31 nombres d’Armstrong se trouvent entre 1 et 10^9. Peux-tu tous les lister sans tester un milliard de nombres un par un ?
Indices
Ouvrez-les un par un. Chacun en dévoile un peu plus.
Avant de pouvoir élever un chiffre à une puissance, tu as besoin de l’exposant. Combien de chiffres comporte
n, et comment peux-tu le déterminer par le calcul ?n % 10est le dernier chiffre, et la division entière par 10 le supprime. Répétez jusqu’à ce qu’il ne reste plus rien : cela parcourt chaque chiffre, et le nombre d’étapes est l’exposantk.Compte les chiffres en un seul passage. Puis extrais-les à nouveau, ajoute chaque chiffre élevé à la puissance
kà un total sur 64 bits, et renvoie si le total est égal aund’origine.
Solution
La définition est l’algorithme : trouver le nombre de chiffres de n, élever chaque chiffre à cette puissance, additionner les résultats et comparer avec n. Les pièges se trouvent dans les nombres. L’exposant est le nombre de chiffres de ce n particulier, et non un 3 fixe, et la somme peut dépasser un entier de 32 bits : pour 999999999, elle vaut 9 × 9^9 = 3486784401.
Lire les chiffres de la chaîne
Intuition
La représentation décimale de n te donne les deux éléments dont tu as besoin. Sa longueur est l’exposant k, et ses caractères sont les chiffres. Pour 9474, la chaîne comporte 4 caractères, donc tu additionnes 9^4 + 4^4 + 7^4 + 4^4.
Convertis chaque caractère en son chiffre, élève-le à la puissance k, puis ajoute-le à un total cumulé. n est un nombre d’Armstrong si et seulement si le total final est égal à n.
Conserve le total dans un entier de 64 bits. n tient sur 32 bits, mais la somme n’y tient pas nécessairement : 999999999 donne 3486784401, qui dépasse la limite de 32 bits, 2147483647. Calculer une puissance avec une boucle de k multiplications coûte k étapes par chiffre, donc le test est en O(k²), avec k d’environ log n. Ici, cela représente au plus 100 multiplications, et la chaîne utilise k caractères de mémoire.
Algorithme
- Convertis
nen sa représentation décimale sous forme de chaîne et noteksa longueur. - Définis un
totalde 64 bits à0. - Pour chaque caractère, convertis-le en chiffre
det ajouted^kàtotal, en multipliant des nombres entiers plutôt qu'en appelant une fonction de puissance à virgule flottante. - Retourne si
totalest égal àn.
def isArmstrong(n):
digits = str(n)
k = len(digits)
total = 0
for ch in digits:
total += int(ch) ** k
return total == nExtrais les chiffres et consulte leurs puissances
Intuition
L’arithmétique seule fait le même travail sans chaîne de caractères. m % 10 est le dernier chiffre de m et la division entière par 10 le supprime : une boucle qui divise par 10 jusqu’à ce qu’il ne reste plus rien compte les chiffres. 9474 devient 947, 94, 9, 0 : quatre étapes, donc k = 4.
Il n’existe que dix chiffres, alors construis une table powers[d] = d^k pour d de 0 à 9 avant d’additionner quoi que ce soit. Chaque chiffre nécessite alors une seule consultation au lieu de k multiplications. La vérification passe à un temps de O(log n), et la table a une taille fixe de dix éléments, soit un espace de O(1).
La deuxième boucle extrait à nouveau les chiffres et ajoute powers[m % 10] au total. Chaque terme est nul ou positif, donc le total ne diminue jamais, et dès qu’il dépasse n, la réponse est false. Pour 999999999, cela se produit après trois chiffres, à 3 × 387420489 = 1162261467. La table nécessite tout de même 64 bits, car n = 10^9 a dix chiffres et 9^10 = 3486784401.
Algorithme
- Comptez les chiffres de
nen divisant une copie par 10 jusqu’à ce qu’elle atteigne 0 ; appelez ce nombrek. - Remplissez
powers[d] = d^kpour chaque chiffredde 0 à 9, dans des entiers 64 bits. - Divisez à nouveau une copie fraîche de
npar 10, en ajoutantpowers[m % 10]àtotalà chaque étape. - Si
totaldépassen, renvoyez immédiatementfalse. - Après le dernier chiffre, renvoyez si
totalest égal àn.
def isArmstrong(n):
# Count the digits: k is the exponent.
k = 0
m = n
while m > 0:
k += 1
m //= 10
# powers[d] = d^k for the ten possible digits.
powers = [d ** k for d in range(10)]
total = 0
m = n
while m > 0:
total += powers[m % 10]
if total > n:
return False # the total only grows
m //= 10
return total == n
Pièges et cas limites
La formule est courte, donc les bogues viennent des nombres qui l’entourent.
- Un exposant fixe de 3. Cela accepte
153et370, mais rejette9474, et rejette tous les nombres à un chiffre supérieurs à 1, puisque7^3 = 343. - Une somme sur 32 bits.
999999999donne la somme3486784401, et l’entrée de la table9^10est le même nombre. En C, ce dépassement de capacité entraîne un comportement indéfini ; Java et C# reviennent à un nombre négatif, et une compilation Rust en mode débogage déclenche une panique. Utilisezlong,long longoui64. - Les puissances en virgule flottante.
powen C etMath.powen Java renvoient undouble. Certains environnements d’exécution C ont renvoyé une valeur légèrement inférieure à un nombre entier, comme24.999...pour5^2, qu’une conversion tronque à24. Multipliez plutôt des nombres entiers dans une boucle. - Comparer avec la mauvaise valeur. Les boucles sur les chiffres divisent
njusqu’à 0 ; travaillez donc sur une copie et comparez le total à la valeur d’origine. - La notation scientifique. En R,
as.character(1e9)est"1e+09", soit cinq caractères ; une solution en R basée sur les chaînes formate donc avecsprintf("%.0f", n).
Questions fréquentes3
Qu’est-ce qu’un nombre d’Armstrong ?
Un nombre d’Armstrong, également appelé nombre narcissique, est égal à la somme de ses propres chiffres, chacun élevé à la puissance du nombre de chiffres. 153 en est un, car 1^3 + 5^3 + 3^3 = 153, et 9474 en est un, car 9^4 + 4^4 + 7^4 + 4^4 = 9474. Tout nombre à un chiffre convient, puisque d^1 = d.
Combien y a-t-il de nombres d’Armstrong ?
En base 10, il existe exactement 88 nombres positifs égaux à la somme des puissances de leurs chiffres, et le plus grand a 39 chiffres. La liste est finie, car un nombre de k chiffres est au moins égal à 10^(k-1), tandis que la somme des puissances de ses chiffres est au plus égale à k × 9^k, et à partir de 61 chiffres, la somme ne peut jamais rattraper son retard. Entre 1 et 10^9, il y en a 31.
Pourquoi la vérification d’un nombre d’Armstrong nécessite-t-elle un entier de 64 bits ?
La valeur d’entrée tient sur 32 bits, mais la somme des chiffres élevés à une puissance peut être plusieurs fois supérieure au nombre. 999999999 donne 9 × 9^9 = 3486784401, ce qui dépasse 2^31-1 = 2147483647. Un total sur 32 bits déborde dans ce cas ; stocke donc le total et les puissances dans un type sur 64 bits.
Problèmes similaires
Des problèmes qui reposent sur les mêmes idées. En résoudre deux ou trois, c’est ce qui ancre un schéma.
def isArmstrong(n):
# Écrivez le code iciTest #1
Test #2
Test #3
Argument
n = 153
Résultat attendu
true