Exercices sur les nombres et les suites
Cette section présente des exercices sur les propriétés des nombres (nombres heureux, nombres distincts) et sur des suites particulières comme la suite de Robinson.
Nombres heureux
Un nombre heureux est un entier qui, lorsqu'on remplace itérativement le nombre par la somme des carrés de ses chiffres, finit par atteindre le chiffre 1.
Exemple — N = 7
- 7² = 49
- 4² + 9² = 16 + 81 = 97
- 9² + 7² = 81 + 49 = 130
- 1² + 3² + 0² = 1 + 9 + 0 = 10
- 1² + 0² = 1 ✓
On est arrivé à 1 → N = 7 est heureux.
Travail demandé :
Écrire une fonction heureux(nb) qui détermine si un entier nb est heureux ou non.
— On atteint 1 → nombre heureux.
— On retombe sur un nombre déjà rencontré → cycle infini → nombre non heureux.
Pour détecter un cycle, on mémorise les valeurs intermédiaires dans un
set.- Convertir le nombre en chaîne pour accéder à ses chiffres.
- Calculer
s = Σ chiffre². - Si
s == 1→ retournerTrue. - Si
sest déjà dans l'historique → cycle → retournerFalse. - Sinon, ajouter
sà l'historique et recommencer avecs.
def heureux(nb):
"""
Détermine si un nombre est heureux.
Retourne True si heureux, False sinon.
"""
nombre = str(nb)
historique = set() # mémorise les valeurs vues pour détecter les cycles
while True:
# Somme des carrés des chiffres
s = sum(int(c) ** 2 for c in nombre)
nombre = str(s)
if nombre == '1':
return True # nombre heureux
if nombre in historique:
return False # cycle détecté → non heureux
historique.add(nombre)
# Tests
print(f"7 est heureux ? {heureux(7)}") # True
print(f"4 est heureux ? {heureux(4)}") # False (cycle : 4→16→37→58→89→…→4)
print(f"19 est heureux ? {heureux(19)}") # True (19→82→68→100→1)def somme_carres(n):
"""Somme des carrés des chiffres de n."""
return sum(int(c) ** 2 for c in str(n))
def heureux(nb):
"""Version concise avec algorithme de Floyd (lièvre et tortue)."""
lent = somme_carres(nb)
rapide = somme_carres(somme_carres(nb))
# Chercher un cycle avec deux vitesses
while lent != 1 and lent != rapide:
lent = somme_carres(lent)
rapide = somme_carres(somme_carres(rapide))
return lent == 1
print(f"7 → {heureux(7)}") # True
print(f"4 → {heureux(4)}") # False
print(f"19 → {heureux(19)}") # True7 est heureux ? True 4 est heureux ? False 19 est heureux ? True
set.7, 4, 19
True, False, True
Nombres distincts
Un entier est dit distinct s'il est composé de chiffres tous différents.
Écrire une fonction estdistinct(nb) qui vérifie et affiche si nb est distinct ou non.
Exemples
- N = 1273 → chiffres {1, 2, 7, 3} tous différents → "est distinct"
- N = 1565 → chiffres {1, 5, 6, 5} — le 5 se répète → "est non distinct"
def estdistinct(n):
"""
Vérifie si les chiffres de n sont tous distincts.
Méthode : count() sur la chaîne de caractères.
Complexité : O(d²) où d = nombre de chiffres.
"""
if n <= 0:
print('Le nombre doit être positif')
return
ch = str(n)
for chiffre in ch:
if ch.count(chiffre) > 1: # chiffre apparaît plus d'une fois
print(n, 'est non distinct')
return
print(n, 'est distinct')
# Tests
estdistinct(1273)
estdistinct(1565)def estdistinct(n):
"""
Vérifie si les chiffres de n sont tous distincts.
Méthode : ensemble — un set ne contient pas de doublons.
Complexité : O(d) où d = nombre de chiffres.
Propriété : len(set(ch)) == len(ch) ssi tous les chiffres sont uniques.
"""
ch = str(n)
if len(set(ch)) == len(ch):
print(n, 'est distinct')
else:
print(n, 'est non distinct')
# Tests
estdistinct(1273) # est distinct
estdistinct(1565) # est non distinct
estdistinct(12345) # est distinct
estdistinct(11234) # est non distinct1273 est distinct 1565 est non distinct 12345 est distinct 11234 est non distinct
set Python élimine automatiquement les doublons. Si set("1565") = {'1','5','6'} (taille 3) ≠ len("1565") (4), c'est qu'il y a un doublon. C'est la méthode la plus concise et efficace : O(d).1273, 1565
1273 est distinct 1565 est non distinct
set("1273") = {'1','2','7','3'}, taille 4 = len("1273") → distinct. 1565 → set("1565") = {'1','5','6'}, taille 3 ≠ len("1565") = 4 → non distinct.Suite de Robinson
La suite de Robinson est définie par :
- U₀ = 0
- Uₙ se construit en concaténant le nombre d'apparitions de chaque chiffre de Uₙ₋₁ suivi du chiffre lui-même, dans l'ordre décroissant des chiffres, pour tout n > 0.
Développement de la suite pour n = 5
- U₀ = 0
- U₁ = 10 → 1 apparition du chiffre 0
- U₂ = 1110 → 1 fois le chiffre 1, 1 fois le chiffre 0
- U₃ = 3110 → 3 fois le chiffre 1, 1 fois le chiffre 0
- U₄ = 132110 → 1 fois 3, 2 fois 1, 1 fois 0
- U₅ = 13123110 → 1 fois 3, 1 fois 2, 3 fois 1, 1 fois 0
Travail demandé :
Écrire une fonction robinson(N) calculant le N-ième terme de la suite.
- Compter les occurrences de chaque chiffre (0–9) dans Uₙ₋₁.
- Parcourir les chiffres de 9 à 0 (ordre décroissant).
- Pour chaque chiffre présent : concaténer
count + chiffre.
def robinson(n):
"""
Calcule et affiche les n premiers termes de la suite de Robinson.
Retourne le n-ième terme.
"""
U = 0 # U₀
for k in range(1, n + 1):
ch = str(U)
# Tableau de comptage pour les chiffres 0 à 9
L = [0] * 10
for chiffre in ch:
L[int(chiffre)] += 1
# Construire Uₖ : ordre décroissant des chiffres
res = ''
for j in range(9, -1, -1):
if L[j] != 0:
res += str(L[j]) + str(j)
U = int(res)
print(f'U_{k} = {U}')
return U
robinson(5)from collections import Counter
def robinson_detail(n):
"""
Version pédagogique avec explications étape par étape.
Utilise Counter pour le comptage.
"""
U = 0
print(f"U₀ = {U}")
for k in range(1, n + 1):
ch = str(U)
compte = Counter(ch) # {'1': 3, '0': 1, ...}
print(f"\n Uₙ₋₁ = {ch}")
# Construire Uₖ : ordre décroissant (9 → 0)
res = ''
for j in range(9, -1, -1):
c = compte.get(str(j), 0)
if c > 0:
print(f" {c} fois le chiffre {j} → '{c}{j}'")
res += str(c) + str(j)
U = int(res)
print(f" → U_{k} = {U}")
print(f"\nTerme {n} : {U}")
return U
robinson_detail(5)U_1 = 10 U_2 = 1110 U_3 = 3110 U_4 = 132110 U_5 = 13123110
Dans U₄ = 132110 : chiffre 3 → 1 fois, chiffre 2 → 1 fois, chiffre 1 → 2 fois, chiffre 0 → 1 fois.
En ordre décroissant :
"13" + "12" + "21" + "10" = "13122110".Attention : le terme exact de l'énoncé est 13123110 — vérifier la valeur de U₄ = 132110 qui contient 1×3, 2×1, 1×0 → "13" + "21" + "10" = "132110" ✓. Donc U₅ : dans 132110 on a 1×3, 2×1, 1×2, 1×0 (U₄ contient les chiffres 1,3,2,1,1,0) →
"13"+"12"+"31"+"10" = 13123110 ✓N = 5
U₅ = 13123110
Récapitulatif
| Exercice | Fonctionnalité | Méthode clé | Complexité |
|---|---|---|---|
| Nombres heureux | Vérifier si un nombre est heureux | Itération + détection de cycle (set ou Floyd) | O(k) — k = longueur du cycle |
| Nombres distincts | Vérifier si les chiffres sont uniques | len(set(ch)) == len(ch) | O(d) — d = nb de chiffres |
| Suite de Robinson | Générer le n-ième terme | Comptage + construction en ordre décroissant | O(n × log Uₙ) |
- Les nombres heureux illustrent l'importance de la détection de cycles — sans elle, l'algorithme boucle indéfiniment.
- Pour vérifier l'unicité des chiffres, un ensemble (
set) est plus efficace qu'un comptage manuel : O(d) vs O(d²). - La suite de Robinson est un exemple de suite auto-descriptive, inspirée du célèbre Look-and-Say de John Conway.
- La manipulation des chaînes de caractères est essentielle pour décomposer un entier chiffre par chiffre.
- Le module
collections.Countersimplifie considérablement le comptage de chiffres.
Discussion (0)
Soyez le premier à laisser un commentaire !
Laisser un commentaire
Votre commentaire sera visible après modération.