QCM : Analyse fine des boucles en Python

[enonce]
Ce QCM propose une analyse fine des boucles Python : pièges de bornes, compteurs complexes, boucles while délicates et choix entre for et while. Choisissez la bonne réponse parmi les quatre propositions.
[/enonce]

[etape]
Dans la boucle for i in range(1, 10) :, quelle est la plus grande valeur prise par i ?
[qcm]
[option]$10$[/option]
[option correct="true"]$9$[/option]
[option]$11$[/option]
[option]$1$[/option]
[reponse statut="correct"]Exact !
La borne supérieure de range(a, b) est exclue. Pour range(1, 10), la variable i parcourt $1, 2, 3, \ldots, 9$. La plus grande valeur est donc $9$.[/reponse]
[reponse motif="$10$"]Non.
Piège classique : la borne supérieure $10$ n'est pas atteinte par i. La séquence s'arrête une unité avant la borne.[/reponse]
[reponse motif="$11$"]Non.
$11$ n'apparaît jamais dans range(1, 10) : la séquence va de $1$ à $9$ inclus.[/reponse]
[reponse motif="$1$"]Non.
$1$ est la plus petite valeur prise par i, pas la plus grande. La question porte sur la plus grande.[/reponse]
[reponse statut="incorrect"]Non.
Règle à retenir : range(a, b) parcourt de $a$ à $b - 1$.[/reponse]
[/qcm]
[/etape]

[etape]
Dans les situations suivantes, laquelle exige une boucle while plutôt qu'une boucle for ?
[qcm]
[option]Afficher les $20$ premiers carrés parfaits[/option]
[option]Calculer la somme $1 + 2 + \ldots + 100$[/option]
[option correct="true"]Trouver le plus petit entier $n$ tel que $2^n > 10^6$[/option]
[option]Afficher chaque élément d'une liste donnée[/option]
[reponse statut="correct"]Bonne réponse !
On ne connaît pas à l'avance la valeur de $n$ ; on ne peut donc pas fixer le nombre de tours dans un range. La boucle while est adaptée : on répète tant que $2^n \leqslant 10^6$.[/reponse]
[reponse motif="Afficher les $20$ premiers carrés parfaits"]Non.
Le nombre de répétitions est connu ($20$). On peut donc utiliser for i in range(1, 21) : la boucle for est plus simple.[/reponse]
[reponse motif="Calculer la somme $1 + 2 + \ldots + 100$"]Non.
Le nombre de termes est fixé ($100$). Une boucle for i in range(1, 101) convient parfaitement.[/reponse]
[reponse motif="Afficher chaque élément d'une liste donnée"]Non.
Parcourir une liste dont on connaît les éléments est typiquement le rôle d'une boucle for.[/reponse]
[reponse statut="incorrect"]Non.
Règle : for si le nombre de tours est connu à l'avance, while sinon.[/reponse]
[/qcm]
[/etape]

[etape]
On exécute le programme Python ci-dessous :

c = 0
for i in range(100) :
    if i % 7 == 0 :
        c = c + 1
print(c)

Que s'affiche-t-il ?
[qcm]
[option]$14$[/option]
[option correct="true"]$15$[/option]
[option]$7$[/option]
[option]$100$[/option]
[reponse statut="correct"]Bravo !
Les multiples de $7$ entre $0$ et $99$ sont $0, 7, 14, 21, \ldots, 98$. Le dernier est $98 = 7 \times 14$, mais $0 = 7 \times 0$ est aussi compté. Il y en a donc $14 + 1 = 15$.[/reponse]
[reponse motif="$14$"]Non.
Vous avez oublié de compter $0$, qui est bien divisible par $7$ ($0 = 7 \times 0$). Python considère que $0 \% 7 = 0$, donc $0$ vérifie la condition.[/reponse]
[reponse motif="$7$"]Non.
$7$ est le plus petit multiple non nul de $7$ rencontré, mais la question porte sur le nombre total de multiples de $7$ entre $0$ et $99$.[/reponse]
[reponse motif="$100$"]Non.
$100$ est le nombre total de valeurs parcourues par i, pas le nombre de celles qui vérifient la condition.[/reponse]
[reponse statut="incorrect"]Non.
Les multiples de $7$ entre $0$ et $99$ sont $0, 7, 14, \ldots, 98$. Compter en incluant $0$.[/reponse]
[/qcm]
[/etape]

[etape]
On considère le programme Python ci-dessous :

i = 0
while i < 10 :
    print(i)

Que se passe-t-il lors de l'exécution ?
[qcm]
[option]Le programme affiche $0, 1, 2, \ldots, 9$ puis s'arrête[/option]
[option]Le programme n'affiche rien[/option]
[option correct="true"]Le programme affiche $0$ indéfiniment (boucle infinie)[/option]
[option]Le programme affiche $10$ puis s'arrête[/option]
[reponse statut="correct"]Parfait !
La variable i n'est jamais modifiée à l'intérieur de la boucle. La condition i < 10 reste donc toujours vraie (car $i$ reste à $0$) et la boucle tourne indéfiniment en affichant $0$.[/reponse]
[reponse motif="Le programme affiche $0, 1, 2, \ldots, 9$ puis s'arrête"]Non.
Pour cela, il faudrait incrémenter i à chaque tour avec i = i + 1. Ici, rien ne fait évoluer i.[/reponse]
[reponse motif="Le programme n'affiche rien"]Non.
La condition i < 10 est vraie au premier tour ($0 < 10$), donc le bloc s'exécute au moins une fois. Un print s'effectue donc.[/reponse]
[reponse motif="Le programme affiche $10$ puis s'arrête"]Non.
La boucle while ne s'arrête pas pile sur une valeur précise : elle continue tant que la condition est vraie. Et ici, rien ne rend la condition fausse.[/reponse]
[reponse statut="incorrect"]Non.
Rechercher si i évolue dans le corps de la boucle. Si non, la condition reste inchangée et la boucle ne s'arrête jamais.[/reponse]
[/qcm]
[/etape]

[etape]
On exécute le programme Python ci-dessous :

S = 0
q = 1
for i in range(4) :
    S = S + q
    q = q * 2
print(S)

Que s'affiche-t-il ?
[qcm]
[option]$7$[/option]
[option]$8$[/option]
[option correct="true"]$15$[/option]
[option]$16$[/option]
[reponse statut="correct"]Exactement !
Traçons les étapes avec $S$ et $q$ :
Avant la boucle : $S = 0$, $q = 1$.
Tour $0$ : $S = 0 + 1 = 1$, $q = 2$.
Tour $1$ : $S = 1 + 2 = 3$, $q = 4$.
Tour $2$ : $S = 3 + 4 = 7$, $q = 8$.
Tour $3$ : $S = 7 + 8 = 15$, $q = 16$.
On a calculé $1 + 2 + 4 + 8 = 15$.[/reponse]
[reponse motif="$7$"]Non.
$7 = 1 + 2 + 4$ correspond à seulement trois tours de boucle. Or range(4) en fait quatre. Vérifier le dernier tour.[/reponse]
[reponse motif="$8$"]Non.
$8$ est la valeur de $q$ à la fin d'un certain tour, pas la valeur finale de S. La question porte sur S, le cumul.[/reponse]
[reponse motif="$16$"]Non.
$16$ est la valeur finale de q, pas celle de S. Ne pas confondre la variable de cumul et la variable qui évolue.[/reponse]
[reponse statut="incorrect"]Non.
Faire un tableau avec deux colonnes (S et q) et suivre les quatre tours de boucle.[/reponse]
[/qcm]
[/etape]

[etape]
On souhaite calculer la plus petite valeur de n telle que $1 + 2 + \ldots + n \geqslant 100$. Parmi les programmes ci-dessous, lequel est correct ?
[qcm]
[option]for n in range(100) : S = S + n[/option]
[option correct="true"]S = 0 ; n = 0 ; while S < 100 : n = n + 1 ; S = S + n[/option]
[option]S = 0 ; for n in range(100) : if S < 100 : S = S + n[/option]
[option]n = 0 ; while S >= 100 : n = n + 1 ; S = S + n[/option]
[reponse statut="correct"]Tu as raison !
On ne connaît pas $n$ à l'avance : il faut une boucle while. On incrémente $n$ à chaque tour et on cumule dans $S$ tant que $S < 100$. Dès que le cumul dépasse $100$, la boucle s'arrête et $n$ contient la valeur cherchée.[/reponse]
[reponse motif="for n in range(100) : S = S + n"]Non.
Ce programme ne s'arrête pas quand le seuil est atteint : il parcourt toutes les valeurs jusqu'à $99$. De plus, S n'est pas initialisée.[/reponse]
[reponse motif="S = 0 ; for n in range(100) : if S < 100 : S = S + n"]Non.
Même si le test empêche de cumuler après le seuil, la boucle for tourne toujours $100$ fois (juste sans rien ajouter). On ne s'arrête pas quand on a trouvé $n$.[/reponse]
[reponse motif="n = 0 ; while S >= 100 : n = n + 1 ; S = S + n"]Non.
La condition est inversée : on veut rester dans la boucle tant que S < 100, pas tant que S >= 100. De plus, S n'est pas initialisée.[/reponse]
[reponse statut="incorrect"]Non.
Stratégie : condition d'arrêt inconnue → boucle while. La condition écrite dans while est celle pour rester dans la boucle.[/reponse]
[/qcm]
[/etape]

Vrai/Faux : Boucles while et pièges (niveau 3)

[enonce]
Pour chaque affirmation suivante sur les boucles while et les pièges classiques en Python, indiquez si elle est Vraie ou Fausse.
[/enonce]

[etape]
Affirmation : Dans l'instruction while i < 10 :, le bloc continue de s'exécuter tant que i est inférieur à $10$.

[qcm]
[option correct="true"]Vrai[/option]
[option]Faux[/option]
[reponse statut="correct"]Bravo !
La condition placée après while est celle qui permet de rester dans la boucle.
Dès que i atteint $10$ ou une valeur plus grande, la condition devient fausse et on sort de la boucle.[/reponse]
[reponse statut="incorrect"]Non, cette affirmation est vraie.
Rappel : la condition du while est la condition de continuation (pas de sortie).
Tant que i < 10 est vraie, le bloc est exécuté ; dès qu'elle devient fausse, on sort.[/reponse]
[/qcm]

[solution]
Cette affirmation est vraie. Le while répète le bloc tant que sa condition est vraie.
[/solution]
[/etape]

[etape]
On exécute le programme Python ci-dessous :

i = 1
while i < 1000 :
    i = i * 2
print(i)

Affirmation : Ce programme affiche $512$.

[qcm]
[option]Vrai[/option]
[option correct="true"]Faux[/option]
[reponse statut="correct"]Correct !
La boucle multiplie i par $2$ tant que i < 1000. Les valeurs successives sont $1, 2, 4, 8, \ldots, 512, 1024$.
Lorsque i atteint $512$, la condition i < 1000 est encore vraie, donc on continue : i devient $1024$. Le programme affiche $1024$.[/reponse]
[reponse statut="incorrect"]Non, cette affirmation est fausse.
Attention à ne pas s'arrêter trop tôt.
Tant que i < 1000, on double i. À $512$, la condition est encore vraie, donc i passe à $1024$ ; là, la condition devient fausse et la boucle se termine. Le programme affiche $1024$.[/reponse]
[/qcm]

[solution]
Cette affirmation est fausse. La boucle continue tant que i < 1000. i prend les valeurs $1, 2, 4, \ldots, 512, 1024$, et le programme affiche $1024$.
[/solution]
[/etape]

[etape]
On considère le programme Python ci-dessous :

i = 0
while i < 5 :
    print(i)

Affirmation : Ce programme affiche les entiers de $0$ à $4$ puis s'arrête.

[qcm]
[option]Vrai[/option]
[option correct="true"]Faux[/option]
[reponse statut="correct"]Tu as raison !
La variable i n'est jamais modifiée à l'intérieur de la boucle, elle reste donc à $0$.
La condition i < 5 reste toujours vraie : c'est une boucle infinie qui affiche $0$ sans s'arrêter.[/reponse]
[reponse statut="incorrect"]Non, cette affirmation est fausse.
Le piège classique est d'oublier de modifier la variable de boucle.
i n'est jamais incrémentée, donc la condition reste toujours vraie : le programme affiche $0$ indéfiniment (boucle infinie).[/reponse]
[/qcm]

[solution]
Cette affirmation est fausse. i n'est pas modifiée dans la boucle : la condition reste vraie et le programme boucle à l'infini.
[/solution]
[/etape]

[etape]
On souhaite trouver la plus petite puissance de $3$ strictement supérieure à $100$. On écrit :

p = 1
while p <= 100 :
    p = p * 3
print(p)

Affirmation : Ce programme affiche $243$.

[qcm]
[option correct="true"]Vrai[/option]
[option]Faux[/option]
[reponse statut="correct"]Exactement !
Les puissances successives sont $1, 3, 9, 27, 81, 243$.
À $81$, la condition p <= 100 est encore vraie, donc on passe à $243$. À ce stade, la condition devient fausse et la boucle se termine.[/reponse]
[reponse statut="incorrect"]Non, cette affirmation est vraie.
Il faut suivre la boucle jusqu'à ce que la condition devienne fausse.
p prend les valeurs $1, 3, 9, 27, 81, 243$. La première puissance de $3$ strictement supérieure à $100$ est $243$.[/reponse]
[/qcm]

[solution]
Cette affirmation est vraie. Les puissances successives sont $1, 3, 9, 27, 81, 243$. La boucle s'arrête quand p > 100, donc à $243$.
[/solution]
[/etape]

[etape]
Affirmation : Pour sortir d'une boucle while dès que n dépasse $500$, il faut écrire while n > 500 :.

[qcm]
[option]Vrai[/option]
[option correct="true"]Faux[/option]
[reponse statut="correct"]Bonne réponse !
La condition placée après while est la condition de continuation, pas de sortie.
Pour sortir quand n > 500, il faut continuer tant que n <= 500 : on écrit donc while n <= 500 :.[/reponse]
[reponse statut="incorrect"]Non, cette affirmation est fausse.
Attention à ne pas confondre condition de sortie et condition de continuation.
La condition du while est celle qui permet de rester dans la boucle, donc la négation de la condition de sortie. Il faut écrire while n <= 500 :.[/reponse]
[/qcm]

[solution]
Cette affirmation est fausse. La condition du while est l'opposée de la condition de sortie : il faut écrire while n <= 500 :.
[/solution]
[/etape]

[etape]
On exécute le programme Python ci-dessous :

n = 0
s = 0
while s < 20 :
    n = n + 1
    s = s + n
print(n)

Affirmation : Ce programme affiche $6$.

[qcm]
[option correct="true"]Vrai[/option]
[option]Faux[/option]
[reponse statut="correct"]Bravo !
On suit l'évolution de n et s à chaque tour : $n=1, s=1$ ; $n=2, s=3$ ; $n=3, s=6$ ; $n=4, s=10$ ; $n=5, s=15$ ; $n=6, s=21$.
À ce stade s = 21 n'est plus strictement inférieur à $20$, la boucle s'arrête et n vaut $6$.[/reponse]
[reponse statut="incorrect"]Non, cette affirmation est vraie.
Rappel : il faut dérouler la boucle pas à pas, en notant les valeurs successives de n et s.
La boucle cherche le plus petit $n$ tel que $1 + 2 + \ldots + n \geqslant 20$. Ici $1+2+3+4+5 = 15 < 20$ et $1+2+\ldots+6 = 21 \geqslant 20$, donc $n = 6$.[/reponse]
[/qcm]

[solution]
Cette affirmation est vraie. La boucle s'arrête au premier $n$ tel que $1+2+\ldots+n \geqslant 20$ : c'est $n = 6$ (somme $= 21$).
[/solution]
[/etape]

Python : Au bout de combien d’années le capital double-t-il ?

Le 1ᵉʳ janvier 2025, Lou place $ 5~000 $ € sur un livret rémunéré au taux annuel de $ 3{,}5~\% $. Chaque année, au 1ᵉʳ janvier, les intérêts sont ajoutés au capital : le capital est ainsi multiplié par $ 1{,}035 $.

  1. Vérifier que le capital de Lou s'élève à $ 5~175 $ € au 1ᵉʳ janvier 2026.
  2. On souhaite déterminer l'année à partir de laquelle le capital de Lou dépassera $ 10~000 $ €. Expliquer pourquoi on ne peut pas répondre à cette question avec une boucle for.
  3. Compléter le programme Python ci-dessous pour qu'il affiche le nombre d'années nécessaires pour que le capital dépasse $ 10~000 $ €.

    capital = 5000
    n = 0
    while ... :
        capital = ...
        n = ...
    print(n)
  4. Écrire une fonction duree(C, t, S) qui renvoie le nombre d'années nécessaires pour qu'un capital initial $ C $ placé au taux annuel $ t~\% $ dépasse la somme $ S $.
    Vérifier que l'appel duree(5000, 3.5, 10000) donne bien le résultat de la question 3.

Corrigé

  1. Au 1ᵉʳ janvier 2026, le capital vaut $ 5~000 \times 1{,}035 = \mathbf{5~175} $ €.
  2. On ne connaît pas à l'avance le nombre d'années à attendre : il faut répéter la multiplication par $ 1{,}035 $ tant que le capital reste inférieur à $ 10~000 $ €. Une boucle while est donc adaptée.
  3. À chaque passage dans la boucle, on multiplie le capital par $ 1{,}035 $ et on incrémente le compteur $ n $ :

    capital = 5000
    n = 0
    while capital < 10000:
        capital = capital * 1.035
        n = n + 1
    print(n)

    Ce programme affiche $ 21 $.
    Vérification : au bout de $ 20 $ ans, le capital vaut $ 5~000 \times 1{,}035^{20} \approx 9~948{,}94 $ € (encore inférieur à $ 10~000 $ €). Au bout de $ 21 $ ans, il vaut $ 5~000 \times 1{,}035^{21} \approx 10~297{,}16 $ €, ce qui dépasse $ 10~000 $ €.
    Le capital de Lou dépassera donc $ 10~000 $ € au bout de $ 21 $ ans, c'est-à-dire le 1ᵉʳ janvier 2046.

  4. On remplace les valeurs numériques par les paramètres C, t et S :

    def duree(C, t, S):
        capital = C
        n = 0
        while capital < S:
            capital = capital * (1 + t / 100)
            n = n + 1
        return n

    Test :

    >>> duree(5000, 3.5, 10000)
    21

→ Pour réviser : Choisir entre une boucle for et une boucle while

Algorithme : Jeu du plus ou moins

Vous devez écrire un programme Python pour le jeu du « Plus ou moins » Au départ, le programme va choisir au hasard un nombre « mystère » compris entre 1 et 99 (on utilisera l'instruction randint(1, 99) du module random).

Ensuite, le joueur propose un nombre.

Si c'est le nombre mystère, le programme affiche « Vous avez gagné ! » et le nombre de coup(s) qui ont été nécessaire(s) pour trouver le nombre mystère.

Sinon, le programme indique si le nombre proposé est trop petit ou trop grand jusqu'à ce que le joueur ait trouvé le nombre mystère.

Corrigé

Le nombre de propositions n'est pas connu à l'avance : on utilise donc une boucle while (boucle non bornée) qui se répète tant que le joueur n'a pas trouvé le nombre mystère.

from random import randint

nombre_mystere = randint(1, 99)
nombre_coups = 0
saisie = -1

while saisie != nombre_mystere:
    saisie = int(input("Veuillez entrer un nombre : "))
    nombre_coups = nombre_coups + 1
    if saisie == nombre_mystere:
        print("Vous avez gagne !")
    elif saisie < nombre_mystere:
        print("Le nombre mystere est plus grand !")
    else:
        print("Le nombre mystere est plus petit !")

print(nombre_coups, "coup(s) ont ete necessaire(s) pour reussir.")

L'instruction randint(1, 99) (importée depuis le module random) tire un entier au hasard entre $1$ et $99$. La variable nombre_coups compte le nombre de propositions du joueur.

Algorithme : Liste d’entiers

On souhaite écrire un algorithme qui demande à l'utilisateur d'entrer un entier naturel n puis affiche tous les nombres entiers de 0 à n.

Voici trois propositions d'algorithmes.

Algorithme 1
Variables i, n
Entrée

  • Lire n

Traitement

  • Pour i allant de 0 à n

    • Afficher i
    • i prend la valeur i + 1
  • Fin Pour

Algorithme 2
Variables i, n
Entrée

  • Lire n

Traitement

  • i prend la valeur 0
  • Tant que i inférieur ou égal à n

    • Afficher i
    • i prend la valeur i + 1
  • Fin Tant que

Algorithme 3
Variables i, n
Entrée

  • Lire n

Traitement

  • i prend la valeur 0
  • Tant que i inférieur ou égal à n

    • Afficher i
  • Fin Tant que

Un seul de ces algorithmes est correct. Lequel ? (Justifier votre réponse.)

Corrigé

L'Algorithme 2 est le seul correct.

Dans l'algorithme 1, l'instruction :
i prend la valeur i+1
est en trop.

Dans une boucle « Pour », l'indice est automatiquement incrémenté. Il ne faut pas l'incrémenter une seconde fois.

Dans l'algorithme 3 au contraire, l'instruction :
i prend la valeur i+1
est manquante.

Dans une boucle « Tant que », l'indice n'est pas automatiquement incrémenté.

La valeur de i restera donc à 0. La condition « i inférieur ou égal à n » sera donc toujours vérifiée et l'algorithme tournera alors indéfiniment.