Solution de Suite de Fibonacci - Sujet 03 - EP NSI 2025
Énoncé du problème
EXERCICE 1 (10 points)
On s’intéresse à la suite d’entiers définie par :
- les deux premières valeurs sont égales à 1 ;
- ensuite, chaque valeur est obtenue en faisant la somme des deux valeurs qui la précèdent.
La troisième valeur est donc 1 + 1 = 2, la quatrième est 1 + 2 = 3, la cinquième est 2 + 3 = 5, la sixième est 3 + 5 = 8, et ainsi de suite.
Cette suite d’entiers est connue sous le nom de suite de Fibonacci.
Écrire en Python une fonction fibonacci qui prend en paramètre un entier n supposé strictement positif et qui renvoie le terme d’indice n de cette suite.
Exemples :
>>> fibonacci(1)
1
>>> fibonacci(2)
1
>>> fibonacci(25)
75025
EXERCICE 2 (10 points)
On considère la fonction eleves_du_mois prenant en paramètres eleves et notes deux tableaux non vides de même longueur, le premier contenant le nom des élèves et le second, des entiers positifs désignant leur note à un contrôle de sorte que eleves[i] a obtenu la note notes[i].
Cette fonction renvoie le couple constitué de la note maximale attribuée et des noms des élèves ayant obtenu cette note regroupés dans un tableau.
Ainsi, l’instruction eleves_du_mois(['a', 'b', 'c', 'd'], [15, 18, 12, 18]) renvoie le couple (18, ['b', 'd']).
Compléter le code suivant :
def eleves_du_mois(eleves, notes):
note_maxi = 0
meilleurs_eleves = ...
for i in range(...):
if notes[i] == ...:
meilleurs_eleves.append(...)
elif notes[i] > note_maxi:
note_maxi = ...
meilleurs_eleves = [...]
return (note_maxi, meilleurs_eleves)
Exemples :
>>> eleves_nsi = ['a','b','c','d','e','f','g','h','i','j']
>>> notes_nsi = [30, 40, 80, 60, 58, 80, 75, 80, 60, 24]
>>> eleves_du_mois(eleves_nsi, notes_nsi)
(80, ['c', 'f', 'h'])
Les contraintes ci-dessous sont ajoutées par la plateforme et ne font pas partie du sujet.
Exercice 1
Contraintes :
nest un entier avec1 <= n <= 30- l’indexation commence à 1 : le terme d’indice 1 et le terme d’indice 2 valent tous les deux 1
fibonacci(n)renvoie un entier
Exercice 2
Contraintes :
elevesetnotessont deux tableaux non vides de même longueur :1 <= len(eleves) == len(notes) <= 10^3eleves[i]est une chaîne de caractères non vide de longueur au plus 20 ; les noms ne sont pas nécessairement deux à deux distinctsnotes[i]est un entier positif :0 <= notes[i] <= 10^4eleves_du_mois(eleves, notes)renvoie un couple(entier, tableau de chaînes), le tableau contenant les noms des élèves ayant la note maximale dans l’ordre où ils apparaissent danseleves
Solution
Correction - Sujet 03 - EP NSI 2025
Exercice 1 - la suite de Fibonacci
L’idée. Pour connaître un terme de la suite, il suffit de connaître les deux termes qui le précèdent. On part donc des deux premiers termes, qui valent 1 et 1, et on avance d’un cran à la fois : à chaque tour on calcule le terme suivant en additionnant les deux termes courants, puis on oublie le plus ancien des deux. Quand on est arrivé à l’indice n, on renvoie le dernier terme calculé.
Un petit exemple. Pour n = 5, on part de 1 et 1, puis on calcule 1 + 1 = 2, puis 1 + 2 = 3, puis 2 + 3 = 5. On a fait 3 tours de boucle, c’est-à-dire n - 2 tours, et on obtient fibonacci(5) = 5.
def fibonacci(n):
avant_dernier = 1
dernier = 1
# Pour n = 1 ou n = 2 la boucle ne tourne pas : on renvoie directement 1
for i in range(n - 2):
# On decale la fenetre de deux termes d'un cran vers la droite
nouveau = avant_dernier + dernier
avant_dernier = dernier
dernier = nouveau
return dernier
avant_dernier et dernier contiennent toujours deux termes consécutifs de la suite. Au départ ce sont les termes d’indices 1 et 2, et après k tours ce sont ceux d’indices k + 1 et k + 2 : c’est pour cela qu’il faut exactement n - 2 tours pour que dernier soit le terme d’indice n. Attention à l’ordre des trois affectations : on calcule nouveau avant d’écraser avant_dernier, sinon on perdrait la valeur dont on a besoin. Enfin, range(n - 2) est vide quand n vaut 1 ou 2, donc ces deux cas sont traités sans qu’on ait à écrire de test particulier.
Une version récursive, qui traduit directement la définition de la suite, est tout aussi correcte ici : comme n ne dépasse pas 30, elle reste assez rapide.
Exercice 2 - les élèves du mois
L’idée. On parcourt les élèves une seule fois, en gardant au fur et à mesure la meilleure note vue jusqu’ici dans note_maxi, et la liste des élèves qui l’ont obtenue dans meilleurs_eleves. Pour chaque élève il n’y a que deux cas intéressants : soit sa note est égale au maximum courant et on l’ajoute à la liste, soit elle est strictement plus grande et il devient le seul meilleur élève, ce qui remet la liste à zéro. Si sa note est plus petite, on ne fait rien.
Un petit exemple. Avec ['a', 'b', 'c', 'd'] et [15, 18, 12, 18] : a fait passer le maximum à 15 avec la liste ['a'], b fait passer le maximum à 18 avec la liste ['b'], c à 12 est ignoré, et d à 18 égale le maximum donc on l’ajoute. On renvoie (18, ['b', 'd']).
def eleves_du_mois(eleves, notes):
note_maxi = 0
meilleurs_eleves = []
for i in range(len(eleves)):
# Le cas d'egalite est teste en premier : on ajoute au palmares en cours
if notes[i] == note_maxi:
meilleurs_eleves.append(eleves[i])
elif notes[i] > note_maxi:
# Nouveau maximum : le palmares precedent ne vaut plus rien
note_maxi = notes[i]
meilleurs_eleves = [eleves[i]]
return (note_maxi, meilleurs_eleves)
Les six trous se remplissent presque tout seuls une fois l’idée posée : la liste de départ est vide, la boucle parcourt tous les indices avec range(len(eleves)), on compare notes[i] à note_maxi, et on ajoute eleves[i] ou on repart de [eleves[i]].
Deux points méritent attention. D’abord, meilleurs_eleves = [eleves[i]] crée une nouvelle liste ne contenant que cet élève : c’est bien ce qu’on veut, puisque tous les précédents sont maintenant battus. Ensuite, l’initialisation note_maxi = 0 fonctionne parce que les notes sont des entiers positifs : aucune note ne peut être inférieure à 0. Si toutes les notes valent 0, la première branche s’applique à chaque élève et la fonction renvoie (0, tous les noms), ce qui est bien la réponse attendue.
Comme on ajoute les noms dans l’ordre du parcours, le tableau renvoyé respecte automatiquement l’ordre d’apparition dans eleves.