Compléter un programme avec une boucle
[enonce]
Une association récolte des dons. Chaque semaine, le montant collecté augmente de $3$ euros : $3$ euros la première semaine, $6$ euros la deuxième, $9$ euros la troisième, et ainsi de suite jusqu'à la dixième semaine.
On souhaite écrire un programme Python qui calcule le total récolté au bout des $10$ semaines, c'est-à-dire la somme $3 + 6 + 9 + \ldots + 30$. Le programme est donné à trous : il s'agit de le compléter ligne par ligne, puis d'anticiper son affichage.
[/enonce]
[etape]
On hésite entre une boucle for et une boucle while pour parcourir les $10$ semaines. Quel type de boucle convient le mieux ici ?
[qcm]
[option correct="true"]Une boucle for[/option]
[option]Une boucle while[/option]
[option]Les deux sont impossibles ici[/option]
[reponse statut="correct"]Exactement !
Le nombre de répétitions est connu d'avance : $10$ semaines.
Une boucle for avec range est donc la plus adaptée, car elle est faite pour répéter un nombre de fois fixé à l'avance.[/reponse]
[reponse motif="Une boucle while"]Une boucle while reste possible techniquement, mais elle n'est pas la plus naturelle ici.
Repenser à la question décisive : connaît-on à l'avance le nombre de tours à effectuer ?[/reponse]
[reponse statut="incorrect"]Les deux types de boucles peuvent répéter des instructions.
Se demander lequel est le plus adapté quand le nombre de répétitions est connu dès le départ.[/reponse]
[/qcm]
[/etape]
[etape]
Avant la boucle, il faut préparer la variable qui contiendra le total récolté. On la nomme S. Écrire la ligne d'initialisation de S.
[code-python id="init" attendu="S = 0"]
[reponse statut="correct"]Correct !
Comme aucun euro n'a encore été ajouté, le total démarre à $0$.[/reponse]
[reponse motif="S == 0"]Le double signe == sert à comparer deux valeurs, pas à affecter une valeur à une variable.[/reponse]
[reponse motif="S = 1"]Vérifier la valeur de départ : combien la somme contient-elle avant le premier ajout ?[/reponse]
[reponse statut="incorrect"]On affecte une valeur de départ à S avec le signe = simple.
Quelle valeur neutre choisir pour une somme qui n'a encore rien accumulé ?[/reponse]
[aide essai="2"]Pour une somme, la valeur de départ doit être neutre : ajouter cette valeur ne change rien au total.[/aide]
[aide essai="3"]La ligne est de la forme S = ... où ... est la valeur de départ d'une somme.[/aide]
[/code-python]
[solution]
S = 0
[/solution]
[/etape]
[etape]
La boucle est écrite for i in range(1, ...) de façon à ce que i prenne successivement les valeurs $1, 2, 3, \ldots, 10$. Par quelle valeur faut-il remplacer les pointillés pour que la borne supérieure $10$ soit bien parcourue ?
[math id="borne" attendu="11"]
[reponse statut="correct"]Exactement !
Avec range(1, 11), la valeur $11$ est exclue : i parcourt donc bien $1, 2, \ldots, 10$.[/reponse]
[reponse motif="10"]Avec range, la borne supérieure indiquée n'est jamais atteinte : elle est exclue. Vérifier si $10$ serait alors parcouru.[/reponse]
[reponse statut="incorrect"]Penser à la règle des bornes de range(a, b) : la première est incluse, la seconde est exclue.[/reponse]
[aide essai="2"]Dans range(a, b), les valeurs vont de a inclus jusqu'à b exclu.[/aide]
[aide essai="3"]Pour que le dernier tour utilise $i = 10$, la borne supérieure doit valoir un de plus que $10$.[/aide]
[/math]
[solution]La borne supérieure doit valoir $\mathbf{11}$ : avec range(1, 11), la variable i prend les valeurs $1, 2, \ldots, 10$, car $11$ est exclu.[/solution]
[/etape]
[etape]
À chaque tour de boucle, le montant de la semaine vaut $3 \times i$ euros (semaine $1$ : $3$, semaine $2$ : $6$, etc.). Écrire la ligne, à l'intérieur de la boucle, qui ajoute ce montant au total S.
[code-python id="accu" attendu="S = S + 3*i" indent="1" variantes="S = S + 3 * i || S = 3*i + S || S += 3*i"]
[reponse statut="correct"]Bien vu !
À chaque tour, le total est augmenté du montant de la semaine, ce qui réalise l'accumulation des dons.[/reponse]
[reponse motif="S = 3*i"]Cette ligne écrase le total à chaque tour au lieu de l'augmenter : il faut repartir de la valeur déjà accumulée dans S.[/reponse]
[reponse motif="S = S + i"]Le montant ajouté n'est pas i mais le montant de la semaine. Relire comment ce montant se calcule à partir de i.[/reponse]
[reponse statut="incorrect"]On veut ajouter le montant de la semaine au total déjà obtenu : la ligne réutilise donc S dans son calcul.[/reponse]
[aide essai="2"]Le principe d'accumulation : S = S + (terme à ajouter). Ici le terme est le montant de la semaine.[/aide]
[aide essai="3"]Le montant de la semaine s'écrit 3*i. La ligne réutilise l'ancienne valeur de S.[/aide]
[/code-python]
[solution]
S = S + 3*i
[/solution]
[/etape]
[etape]
Le programme complet est donc :
S = 0
for i in range(1, 11):
S = S + 3*i
print(S)
Quelle valeur s'affiche à l'écran à la fin de l'exécution ?
[math id="total" attendu="165"]
[reponse statut="correct"]Parfait !
La boucle ajoute $3, 6, 9, \ldots, 30$, dont la somme vaut $165$ : c'est le total affiché par print(S).[/reponse]
[reponse motif="30"]$30$ est le montant de la dernière semaine, pas le total accumulé sur les dix semaines.[/reponse]
[reponse motif="55"]$55$ est la somme $1 + 2 + \ldots + 10$. Or chaque terme ajouté n'est pas i mais le montant de la semaine.[/reponse]
[reponse motif="150"]Recompter le nombre de termes : la boucle effectue bien dix tours, de la semaine $1$ à la semaine $10$.[/reponse]
[reponse statut="incorrect"]Additionner les dix montants successifs, ou remarquer qu'ils sont tous multiples de $3$.[/reponse]
[aide essai="2"]Les montants ajoutés sont $3, 6, 9, \ldots, 30$. On peut factoriser par $3$.[/aide]
[aide essai="3"]La somme vaut $3 \times (1 + 2 + \ldots + 10)$. Calculer d'abord la parenthèse.[/aide]
[/math]
[solution]Les montants ajoutés sont $3, 6, 9, \ldots, 30$, soit $3 \times (1 + 2 + \ldots + 10) = 3 \times 55$.
Le programme affiche donc $\mathbf{165}$.[/solution]
[/etape]
[etape]
On modifie maintenant le projet : l'association veut savoir au bout de combien de semaines le total récolté atteint ou dépasse $100$ euros. Cette fois, le nombre de tours n'est plus connu d'avance. Quel type de boucle est désormais le plus adapté ?
[qcm]
[option]Une boucle for avec range[/option]
[option correct="true"]Une boucle while[/option]
[option]Aucune boucle n'est nécessaire[/option]
[reponse statut="correct"]Tout à fait !
On ne sait pas d'avance combien de semaines seront nécessaires pour atteindre $100$ euros : on répète tant que le total reste inférieur au seuil.
C'est exactement le rôle d'une boucle while.[/reponse]
[reponse motif="Une boucle for avec range"]Une boucle for demande de fixer à l'avance le nombre de tours. Or ici, c'est précisément ce nombre que l'on cherche.[/reponse]
[reponse statut="incorrect"]Il faut bien répéter une addition plusieurs fois.
Comme le nombre de répétitions dépend d'un seuil à atteindre, se demander quelle boucle s'arrête sur une condition.[/reponse]
[/qcm]
[solution]Le nombre de tours dépend d'un seuil à franchir et n'est pas connu d'avance : on utilise une boucle while, qui répète tant que la condition « total inférieur à $100$ » est vraie.
En suivant les totaux successifs $3, 9, 18, 30, 45, 63, 84, 108$, le seuil de $100$ euros est dépassé au bout de $8$ semaines.[/solution]
[/etape]