{
  "chapter": {
    "id": "python-boucles-while",
    "level": "snt",
    "theme": "Programmation",
    "title": "6. Boucles non bornées : while",
    "description": "La boucle while et sa condition de continuation, testée avant chaque\ntour ; la variable qui doit changer pour que la boucle s'arrête ; les\nboucles infinies ; compter les tours ; atteindre un seuil ; choisir\nentre for et while.",
    "prerequisites": [],
    "references": []
  },
  "questions": [
    {
      "id": "q01",
      "difficulty": 1,
      "skills": [
        "while",
        "trace"
      ],
      "title": "Une boucle qui compte",
      "statement": "```python\nn = 0\nwhile n < 3:\n    print(n)\n    n = n + 1\n```\n\nQu'affiche ce programme ?",
      "options": [
        {
          "text": "0, 1 et 2",
          "correct": true,
          "feedback": "Bonne réponse : la boucle tourne tant que `n < 3`. Elle affiche\n0, 1, 2, puis `n` vaut 3 et la condition devient fausse.\n"
        },
        {
          "text": "0, 1, 2 et 3",
          "correct": false,
          "feedback": "Erreur : quand `n` vaut 3, la condition `n < 3` est fausse et\nla boucle s'arrête sans afficher.\n"
        },
        {
          "text": "1, 2 et 3",
          "correct": false,
          "feedback": "Erreur : l'affichage a lieu avant l'ajout de 1, la première\nvaleur affichée est 0.\n"
        },
        {
          "text": "0 et 1",
          "correct": false,
          "feedback": "Erreur : 2 est encore strictement inférieur à 3, un troisième\ntour a lieu.\n"
        }
      ],
      "explanation": "`while` répète son bloc tant que la condition est vraie. La\ncondition est vérifiée avant chaque tour : dès qu'elle est fausse, le\nprogramme passe à la suite."
    },
    {
      "id": "q02",
      "difficulty": 1,
      "skills": [
        "while",
        "trace",
        "condition-arret"
      ],
      "title": "La valeur après la boucle",
      "statement": "```python\nn = 10\nwhile n > 0:\n    n = n - 4\nprint(n)\n```\n\nQu'affiche ce programme ?",
      "options": [
        {
          "text": "`-2`",
          "correct": true,
          "feedback": "Bonne réponse : `n` passe par 6, 2 puis -2. À -2, la condition\n`n > 0` est fausse et la boucle s'arrête.\n"
        },
        {
          "text": "`2`",
          "correct": false,
          "feedback": "Erreur : 2 est encore strictement positif, un tour de plus a\nlieu.\n"
        },
        {
          "text": "`0`",
          "correct": false,
          "feedback": "Erreur : en retirant 4 à chaque fois depuis 10, on ne passe\njamais par 0.\n"
        },
        {
          "text": "`-4`",
          "correct": false,
          "feedback": "Erreur : dès que `n` vaut -2, la boucle s'arrête, on ne retire\npas 4 une fois de plus.\n"
        }
      ],
      "explanation": "À la sortie d'un `while`, la condition est fausse : c'est la\npremière valeur qui la rend fausse que l'on retrouve. Ici, le premier\nnombre négatif ou nul atteint.",
      "variants": [
        {
          "statement": "```python\nn = 10\nwhile n > 0:\n    n = n - 4\nprint(n)\n```\n\nQu'affiche ce programme ?",
          "options": [
            {
              "text": "`-2`",
              "correct": true,
              "feedback": "Bonne réponse : `n` passe par 6, 2 puis -2. À -2, la condition\n`n > 0` est fausse et la boucle s'arrête.\n"
            },
            {
              "text": "`2`",
              "correct": false,
              "feedback": "Erreur : 2 est encore strictement positif, un tour de plus a\nlieu.\n"
            },
            {
              "text": "`0`",
              "correct": false,
              "feedback": "Erreur : en retirant 4 à chaque fois depuis 10, on ne passe\njamais par 0.\n"
            },
            {
              "text": "`-4`",
              "correct": false,
              "feedback": "Erreur : dès que `n` vaut -2, la boucle s'arrête, on ne retire\npas 4 une fois de plus.\n"
            }
          ],
          "explanation": "À la sortie d'un `while`, la condition est fausse : c'est la\npremière valeur qui la rend fausse que l'on retrouve. Ici, le premier\nnombre négatif ou nul atteint."
        },
        {
          "statement": "```python\nn = 14\nwhile n > 0:\n    n = n - 5\nprint(n)\n```\n\nQu'affiche ce programme ?",
          "options": [
            {
              "text": "`-1`",
              "correct": true,
              "feedback": "Bonne réponse : `n` passe par 9, 4 puis -1. À -1, la condition\n`n > 0` est fausse et la boucle s'arrête.\n"
            },
            {
              "text": "`4`",
              "correct": false,
              "feedback": "Erreur : 4 est encore strictement positif, un tour de plus a\nlieu.\n"
            },
            {
              "text": "`0`",
              "correct": false,
              "feedback": "Erreur : en retirant 5 à chaque fois depuis 14, on ne passe\njamais par 0.\n"
            },
            {
              "text": "`-5`",
              "correct": false,
              "feedback": "Erreur : dès que `n` vaut -1, la boucle s'arrête, on ne retire\npas 5 une fois de plus.\n"
            }
          ],
          "explanation": "À la sortie d'un `while`, la condition est fausse : c'est la\npremière valeur qui la rend fausse que l'on retrouve. Ici, le premier\nnombre négatif ou nul atteint."
        },
        {
          "statement": "```python\nn = 9\nwhile n > 0:\n    n = n - 4\nprint(n)\n```\n\nQu'affiche ce programme ?",
          "options": [
            {
              "text": "`-3`",
              "correct": true,
              "feedback": "Bonne réponse : `n` passe par 5, 1 puis -3. À -3, la condition\n`n > 0` est fausse et la boucle s'arrête.\n"
            },
            {
              "text": "`1`",
              "correct": false,
              "feedback": "Erreur : 1 est encore strictement positif, un tour de plus a\nlieu.\n"
            },
            {
              "text": "`0`",
              "correct": false,
              "feedback": "Erreur : en retirant 4 à chaque fois depuis 9, on ne passe\njamais par 0.\n"
            },
            {
              "text": "`-4`",
              "correct": false,
              "feedback": "Erreur : dès que `n` vaut -3, la boucle s'arrête, on ne retire\npas 4 une fois de plus.\n"
            }
          ],
          "explanation": "À la sortie d'un `while`, la condition est fausse : c'est la\npremière valeur qui la rend fausse que l'on retrouve. Ici, le premier\nnombre négatif ou nul atteint."
        }
      ]
    },
    {
      "id": "q03",
      "difficulty": 1,
      "skills": [
        "boucle-infinie",
        "while"
      ],
      "title": "Une variable qui ne bouge pas",
      "statement": "```python\ni = 0\nwhile i < 5:\n    print(i)\n```\n\nQue fait ce programme ?",
      "options": [
        {
          "text": "Il ne s'arrête jamais, `i` ne change pas",
          "correct": true,
          "feedback": "Bonne réponse : rien dans la boucle ne modifie `i`, la\ncondition `i < 5` reste vraie et 0 est affiché sans fin.\n"
        },
        {
          "text": "Il affiche 0, 1, 2, 3 et 4",
          "correct": false,
          "feedback": "Erreur : contrairement à `for`, `while` n'augmente pas la\nvariable tout seul.\n"
        },
        {
          "text": "Il affiche 0 une seule fois",
          "correct": false,
          "feedback": "Erreur : après le premier tour, la condition est toujours vraie\net un nouveau tour commence.\n"
        },
        {
          "text": "Il s'arrête sur une erreur, `i` n'augmente pas",
          "correct": false,
          "feedback": "Erreur : Python ne détecte pas une boucle infinie, il l'exécute.\n"
        }
      ],
      "explanation": "Une boucle `while` ne s'arrête que si quelque chose rend sa condition\nfausse. Oublier de modifier la variable de la condition donne une\nboucle infinie."
    },
    {
      "id": "q04",
      "difficulty": 2,
      "skills": [
        "while",
        "compteur",
        "seuil"
      ],
      "title": "Doubler jusqu'à dépasser",
      "statement": "Une somme placée augmente de 10 % par an. On cherche en combien\nd'années elle double.\n\n```python\nsomme = 100\nannees = 0\nwhile somme < 200:\n    somme = somme * 1.1\n    annees = annees + 1\nprint(annees)\n```\n\nQu'affiche ce programme ?",
      "options": [
        {
          "text": "`8`",
          "correct": true,
          "feedback": "Bonne réponse : après 7 ans, la somme vaut environ 194.9, encore\nsous 200 ; après 8 ans, environ 214.4.\n"
        },
        {
          "text": "`7`",
          "correct": false,
          "feedback": "Erreur : après 7 ans, la somme est encore inférieure à 200, un\ntour de plus est nécessaire.\n"
        },
        {
          "text": "`10`",
          "correct": false,
          "feedback": "Erreur : 10 % par an pendant 10 ans ne fait pas 100 %, la\ncroissance se compose et la somme atteint 200 avant.\n"
        },
        {
          "text": "`2`",
          "correct": false,
          "feedback": "Erreur : 2 serait le facteur de multiplication, pas le nombre\nd'années.\n"
        }
      ],
      "explanation": "Le `while` convient quand on ignore à l'avance le nombre de tours :\non répète jusqu'à atteindre un seuil, en comptant les tours dans une\nvariable.",
      "variants": [
        {
          "statement": "Une somme placée augmente de 10 % par an. On cherche en combien\nd'années elle double.\n\n```python\nsomme = 100\nannees = 0\nwhile somme < 200:\n    somme = somme * 1.1\n    annees = annees + 1\nprint(annees)\n```\n\nQu'affiche ce programme ?",
          "options": [
            {
              "text": "`8`",
              "correct": true,
              "feedback": "Bonne réponse : après 7 ans, la somme vaut environ 194.9, encore\nsous 200 ; après 8 ans, environ 214.4.\n"
            },
            {
              "text": "`7`",
              "correct": false,
              "feedback": "Erreur : après 7 ans, la somme est encore inférieure à 200, un\ntour de plus est nécessaire.\n"
            },
            {
              "text": "`10`",
              "correct": false,
              "feedback": "Erreur : 10 % par an pendant 10 ans ne fait pas 100 %, la\ncroissance se compose et la somme atteint 200 avant.\n"
            },
            {
              "text": "`2`",
              "correct": false,
              "feedback": "Erreur : 2 serait le facteur de multiplication, pas le nombre\nd'années.\n"
            }
          ],
          "explanation": "Le `while` convient quand on ignore à l'avance le nombre de tours :\non répète jusqu'à atteindre un seuil, en comptant les tours dans une\nvariable."
        },
        {
          "statement": "Une somme placée augmente de 5 % par an. On cherche en combien\nd'années elle double.\n\n```python\nsomme = 100\nannees = 0\nwhile somme < 200:\n    somme = somme * 1.05\n    annees = annees + 1\nprint(annees)\n```\n\nQu'affiche ce programme ?",
          "options": [
            {
              "text": "`15`",
              "correct": true,
              "feedback": "Bonne réponse : après 14 ans, la somme vaut environ 198.0, encore\nsous 200 ; après 15 ans, environ 207.9.\n"
            },
            {
              "text": "`14`",
              "correct": false,
              "feedback": "Erreur : après 14 ans, la somme est encore inférieure à 200, un\ntour de plus est nécessaire.\n"
            },
            {
              "text": "`20`",
              "correct": false,
              "feedback": "Erreur : 5 % par an pendant 20 ans ne fait pas 100 %, la\ncroissance se compose et la somme atteint 200 avant.\n"
            },
            {
              "text": "`2`",
              "correct": false,
              "feedback": "Erreur : 2 serait le facteur de multiplication, pas le nombre\nd'années.\n"
            }
          ],
          "explanation": "Le `while` convient quand on ignore à l'avance le nombre de tours :\non répète jusqu'à atteindre un seuil, en comptant les tours dans une\nvariable."
        },
        {
          "statement": "Une somme placée augmente de 20 % par an. On cherche en combien\nd'années elle triple.\n\n```python\nsomme = 100\nannees = 0\nwhile somme < 300:\n    somme = somme * 1.2\n    annees = annees + 1\nprint(annees)\n```\n\nQu'affiche ce programme ?",
          "options": [
            {
              "text": "`7`",
              "correct": true,
              "feedback": "Bonne réponse : après 6 ans, la somme vaut environ 298.6, encore\nsous 300 ; après 7 ans, environ 358.3.\n"
            },
            {
              "text": "`6`",
              "correct": false,
              "feedback": "Erreur : après 6 ans, la somme est encore inférieure à 300, un\ntour de plus est nécessaire.\n"
            },
            {
              "text": "`10`",
              "correct": false,
              "feedback": "Erreur : 20 % par an pendant 10 ans ne fait pas 200 %, la\ncroissance se compose et la somme atteint 300 avant.\n"
            },
            {
              "text": "`3`",
              "correct": false,
              "feedback": "Erreur : 3 serait le facteur de multiplication, pas le nombre\nd'années.\n"
            }
          ],
          "explanation": "Le `while` convient quand on ignore à l'avance le nombre de tours :\non répète jusqu'à atteindre un seuil, en comptant les tours dans une\nvariable."
        }
      ]
    },
    {
      "id": "q05",
      "difficulty": 2,
      "skills": [
        "while",
        "compteur",
        "trace"
      ],
      "title": "Compter les tours",
      "statement": "```python\nx = 1\ntours = 0\nwhile x < 50:\n    x = x * 3\n    tours = tours + 1\nprint(tours, x)\n```\n\nQu'affiche ce programme ?",
      "options": [
        {
          "text": "`4 81`",
          "correct": true,
          "feedback": "Bonne réponse : `x` passe par 3, 9, 27 et 81. Il faut 4\ntours pour dépasser 50.\n"
        },
        {
          "text": "`3 27`",
          "correct": false,
          "feedback": "Erreur : 27 est encore inférieur à 50, un tour de plus a\nlieu.\n"
        },
        {
          "text": "`4 27`",
          "correct": false,
          "feedback": "Erreur : au dernier tour, `x` est multiplié une fois de plus\net vaut 81.\n"
        },
        {
          "text": "`5 243`",
          "correct": false,
          "feedback": "Erreur : à 81, la condition `x < 50` est fausse, la boucle\ns'arrête.\n"
        }
      ],
      "explanation": "Une variable de comptage, augmentée de 1 à chaque tour, permet de\nsavoir combien de fois une boucle `while` a tourné. On lit les deux\nvaleurs à la sortie.",
      "variants": [
        {
          "statement": "```python\nx = 1\ntours = 0\nwhile x < 50:\n    x = x * 3\n    tours = tours + 1\nprint(tours, x)\n```\n\nQu'affiche ce programme ?",
          "options": [
            {
              "text": "`4 81`",
              "correct": true,
              "feedback": "Bonne réponse : `x` passe par 3, 9, 27 et 81. Il faut 4\ntours pour dépasser 50.\n"
            },
            {
              "text": "`3 27`",
              "correct": false,
              "feedback": "Erreur : 27 est encore inférieur à 50, un tour de plus a\nlieu.\n"
            },
            {
              "text": "`4 27`",
              "correct": false,
              "feedback": "Erreur : au dernier tour, `x` est multiplié une fois de plus\net vaut 81.\n"
            },
            {
              "text": "`5 243`",
              "correct": false,
              "feedback": "Erreur : à 81, la condition `x < 50` est fausse, la boucle\ns'arrête.\n"
            }
          ],
          "explanation": "Une variable de comptage, augmentée de 1 à chaque tour, permet de\nsavoir combien de fois une boucle `while` a tourné. On lit les deux\nvaleurs à la sortie."
        },
        {
          "statement": "```python\nx = 1\ntours = 0\nwhile x < 100:\n    x = x * 2\n    tours = tours + 1\nprint(tours, x)\n```\n\nQu'affiche ce programme ?",
          "options": [
            {
              "text": "`7 128`",
              "correct": true,
              "feedback": "Bonne réponse : `x` passe par 2, 4, 8, 16, 32, 64 et 128. Il faut 7\ntours pour dépasser 100.\n"
            },
            {
              "text": "`6 64`",
              "correct": false,
              "feedback": "Erreur : 64 est encore inférieur à 100, un tour de plus a\nlieu.\n"
            },
            {
              "text": "`7 64`",
              "correct": false,
              "feedback": "Erreur : au dernier tour, `x` est multiplié une fois de plus\net vaut 128.\n"
            },
            {
              "text": "`8 256`",
              "correct": false,
              "feedback": "Erreur : à 128, la condition `x < 100` est fausse, la boucle\ns'arrête.\n"
            }
          ],
          "explanation": "Une variable de comptage, augmentée de 1 à chaque tour, permet de\nsavoir combien de fois une boucle `while` a tourné. On lit les deux\nvaleurs à la sortie."
        },
        {
          "statement": "```python\nx = 1\ntours = 0\nwhile x < 60:\n    x = x * 4\n    tours = tours + 1\nprint(tours, x)\n```\n\nQu'affiche ce programme ?",
          "options": [
            {
              "text": "`3 64`",
              "correct": true,
              "feedback": "Bonne réponse : `x` passe par 4, 16 et 64. Il faut 3\ntours pour dépasser 60.\n"
            },
            {
              "text": "`2 16`",
              "correct": false,
              "feedback": "Erreur : 16 est encore inférieur à 60, un tour de plus a\nlieu.\n"
            },
            {
              "text": "`3 16`",
              "correct": false,
              "feedback": "Erreur : au dernier tour, `x` est multiplié une fois de plus\net vaut 64.\n"
            },
            {
              "text": "`4 256`",
              "correct": false,
              "feedback": "Erreur : à 64, la condition `x < 60` est fausse, la boucle\ns'arrête.\n"
            }
          ],
          "explanation": "Une variable de comptage, augmentée de 1 à chaque tour, permet de\nsavoir combien de fois une boucle `while` a tourné. On lit les deux\nvaleurs à la sortie."
        }
      ]
    },
    {
      "id": "q06",
      "difficulty": 2,
      "skills": [
        "while",
        "trace"
      ],
      "title": "Le test vient avant le premier tour",
      "statement": "```python\nn = 5\nwhile n < 5:\n    print(\"tour\")\n    n = n + 1\nprint(\"fin\")\n```\n\nQu'affiche ce programme ?",
      "options": [
        {
          "text": "`fin` seulement",
          "correct": true,
          "feedback": "Bonne réponse : la condition `5 < 5` est fausse dès le départ,\nle bloc n'est jamais exécuté.\n"
        },
        {
          "text": "`tour` puis `fin`",
          "correct": false,
          "feedback": "Erreur : `while` teste la condition avant le premier tour, pas\naprès.\n"
        },
        {
          "text": "`tour` cinq fois puis `fin`",
          "correct": false,
          "feedback": "Erreur : `n` vaut déjà 5, la condition est fausse d'emblée.\n"
        },
        {
          "text": "Rien",
          "correct": false,
          "feedback": "Erreur : le dernier `print` est hors de la boucle et s'exécute.\n"
        }
      ],
      "explanation": "Un `while` peut ne faire aucun tour : sa condition est évaluée avant\nd'entrer dans le bloc. Si elle est fausse au départ, on passe\ndirectement à la suite."
    },
    {
      "id": "q07",
      "difficulty": 2,
      "skills": [
        "while",
        "condition-arret"
      ],
      "title": "Choisir la condition",
      "statement": "Un ventilateur doit tourner tant que la température dépasse 25\ndegrés. Quelle ligne commence correctement la boucle ?",
      "options": [
        {
          "text": "`while temperature > 25:`",
          "correct": true,
          "feedback": "Bonne réponse : la condition d'un `while` exprime ce qui doit\nêtre vrai pour continuer, ici « dépasse 25 ».\n"
        },
        {
          "text": "`while temperature < 25:`",
          "correct": false,
          "feedback": "Erreur : cette boucle tournerait tant qu'il fait frais, c'est\nl'inverse.\n"
        },
        {
          "text": "`while temperature == 25:`",
          "correct": false,
          "feedback": "Erreur : la boucle ne tournerait que pour exactement 25 degrés.\n"
        },
        {
          "text": "`if temperature > 25:`",
          "correct": false,
          "feedback": "Erreur : `if` exécute le bloc une seule fois, il ne répète pas.\n"
        }
      ],
      "explanation": "La condition d'un `while` est une condition de continuation, pas\nd'arrêt : on écrit ce qui doit rester vrai pour refaire un tour."
    },
    {
      "id": "q08",
      "difficulty": 3,
      "skills": [
        "while",
        "trace",
        "division"
      ],
      "title": "Une soustraction répétée",
      "statement": "```python\na = 27\nb = 6\nq = 0\nwhile a >= b:\n    a = a - b\n    q = q + 1\nprint(q, a)\n```\n\nQu'affiche ce programme ?",
      "options": [
        {
          "text": "`4 3`",
          "correct": true,
          "feedback": "Bonne réponse : `a` passe par 21, 15, 9 et 3, en 4 tours.\nÀ 3, `a >= 6` est faux. On obtient le quotient et le reste de 27\npar 6.\n"
        },
        {
          "text": "`4 0`",
          "correct": false,
          "feedback": "Erreur : 27 n'est pas un multiple de 6, il reste 3.\n"
        },
        {
          "text": "`5 -3`",
          "correct": false,
          "feedback": "Erreur : à 3, la condition `a >= b` est fausse, on ne soustrait\npas une fois de plus.\n"
        },
        {
          "text": "`3 9`",
          "correct": false,
          "feedback": "Erreur : 9 est encore supérieur ou égal à 6, un tour de plus a\nlieu.\n"
        }
      ],
      "explanation": "Cette boucle calcule une division euclidienne par soustractions\nsuccessives : le compteur donne le quotient, la valeur restante le\nreste. Une trace tour par tour confirme le résultat.",
      "variants": [
        {
          "statement": "```python\na = 27\nb = 6\nq = 0\nwhile a >= b:\n    a = a - b\n    q = q + 1\nprint(q, a)\n```\n\nQu'affiche ce programme ?",
          "options": [
            {
              "text": "`4 3`",
              "correct": true,
              "feedback": "Bonne réponse : `a` passe par 21, 15, 9 et 3, en 4 tours.\nÀ 3, `a >= 6` est faux. On obtient le quotient et le reste de 27\npar 6.\n"
            },
            {
              "text": "`4 0`",
              "correct": false,
              "feedback": "Erreur : 27 n'est pas un multiple de 6, il reste 3.\n"
            },
            {
              "text": "`5 -3`",
              "correct": false,
              "feedback": "Erreur : à 3, la condition `a >= b` est fausse, on ne soustrait\npas une fois de plus.\n"
            },
            {
              "text": "`3 9`",
              "correct": false,
              "feedback": "Erreur : 9 est encore supérieur ou égal à 6, un tour de plus a\nlieu.\n"
            }
          ],
          "explanation": "Cette boucle calcule une division euclidienne par soustractions\nsuccessives : le compteur donne le quotient, la valeur restante le\nreste. Une trace tour par tour confirme le résultat."
        },
        {
          "statement": "```python\na = 38\nb = 7\nq = 0\nwhile a >= b:\n    a = a - b\n    q = q + 1\nprint(q, a)\n```\n\nQu'affiche ce programme ?",
          "options": [
            {
              "text": "`5 3`",
              "correct": true,
              "feedback": "Bonne réponse : `a` passe par 31, 24, 17, 10 et 3, en 5 tours.\nÀ 3, `a >= 7` est faux. On obtient le quotient et le reste de 38\npar 7.\n"
            },
            {
              "text": "`5 0`",
              "correct": false,
              "feedback": "Erreur : 38 n'est pas un multiple de 7, il reste 3.\n"
            },
            {
              "text": "`6 -4`",
              "correct": false,
              "feedback": "Erreur : à 3, la condition `a >= b` est fausse, on ne soustrait\npas une fois de plus.\n"
            },
            {
              "text": "`4 10`",
              "correct": false,
              "feedback": "Erreur : 10 est encore supérieur ou égal à 7, un tour de plus a\nlieu.\n"
            }
          ],
          "explanation": "Cette boucle calcule une division euclidienne par soustractions\nsuccessives : le compteur donne le quotient, la valeur restante le\nreste. Une trace tour par tour confirme le résultat."
        },
        {
          "statement": "```python\na = 50\nb = 8\nq = 0\nwhile a >= b:\n    a = a - b\n    q = q + 1\nprint(q, a)\n```\n\nQu'affiche ce programme ?",
          "options": [
            {
              "text": "`6 2`",
              "correct": true,
              "feedback": "Bonne réponse : `a` passe par 42, 34, 26, 18, 10 et 2, en 6 tours.\nÀ 2, `a >= 8` est faux. On obtient le quotient et le reste de 50\npar 8.\n"
            },
            {
              "text": "`6 0`",
              "correct": false,
              "feedback": "Erreur : 50 n'est pas un multiple de 8, il reste 2.\n"
            },
            {
              "text": "`7 -6`",
              "correct": false,
              "feedback": "Erreur : à 2, la condition `a >= b` est fausse, on ne soustrait\npas une fois de plus.\n"
            },
            {
              "text": "`5 10`",
              "correct": false,
              "feedback": "Erreur : 10 est encore supérieur ou égal à 8, un tour de plus a\nlieu.\n"
            }
          ],
          "explanation": "Cette boucle calcule une division euclidienne par soustractions\nsuccessives : le compteur donne le quotient, la valeur restante le\nreste. Une trace tour par tour confirme le résultat."
        }
      ]
    },
    {
      "id": "q09",
      "difficulty": 2,
      "skills": [
        "while",
        "for"
      ],
      "title": "for ou while",
      "statement": "Dans laquelle de ces situations une boucle `while` est-elle\nnécessaire, parce qu'on ne connaît pas le nombre de tours à\nl'avance ?",
      "options": [
        {
          "text": "Redemander un code tant qu'il est faux",
          "correct": true,
          "feedback": "Bonne réponse : impossible de savoir combien d'essais seront\nnécessaires. On répète tant que le code est faux.\n"
        },
        {
          "text": "Afficher les nombres de 1 à 100",
          "correct": false,
          "feedback": "Erreur : le nombre de tours est connu, 100, une boucle `for`\nsuffit.\n"
        },
        {
          "text": "Parcourir les lettres d'un mot",
          "correct": false,
          "feedback": "Erreur : le nombre de lettres est connu, `for` parcourt le mot\ndirectement.\n"
        },
        {
          "text": "Additionner dix relevés de température",
          "correct": false,
          "feedback": "Erreur : dix relevés, dix tours, c'est une boucle bornée.\n"
        }
      ],
      "explanation": "`for` sert quand le nombre de répétitions est connu avant de\ncommencer, `while` quand il dépend de ce qui se passe pendant la\nboucle, comme une saisie ou un seuil à atteindre."
    },
    {
      "id": "q10",
      "difficulty": 3,
      "skills": [
        "while",
        "and-or-not",
        "booleen"
      ],
      "title": "Deux conditions de continuation",
      "statement": "```python\nessais = 0\ntrouve = False\nwhile essais < 3 and not trouve:\n    essais = essais + 1\n    if essais == 2:\n        trouve = True\nprint(essais)\n```\n\nQu'affiche ce programme ?",
      "options": [
        {
          "text": "`2`",
          "correct": true,
          "feedback": "Bonne réponse : au tour numéro 2, `trouve` devient vrai ; au\ntest suivant, `not trouve` est faux et la boucle s'arrête.\n"
        },
        {
          "text": "`3`",
          "correct": false,
          "feedback": "Erreur : la boucle s'arrête dès qu'une des deux conditions\ndevient fausse, ici `not trouve` après le tour numéro 2.\n"
        },
        {
          "text": "`1`",
          "correct": false,
          "feedback": "Erreur : après 1 tours, `essais` vaut 1 et `trouve` est\nencore faux, un tour de plus a lieu.\n"
        },
        {
          "text": "`0`",
          "correct": false,
          "feedback": "Erreur : au départ, les deux conditions sont vraies, la boucle\nfait au moins un tour.\n"
        }
      ],
      "explanation": "Avec `and`, la boucle continue seulement si toutes les conditions\nsont vraies. Elle s'arrête dès que l'une devient fausse : le nombre\nmaximal d'essais ou la réussite.",
      "variants": [
        {
          "statement": "```python\nessais = 0\ntrouve = False\nwhile essais < 3 and not trouve:\n    essais = essais + 1\n    if essais == 2:\n        trouve = True\nprint(essais)\n```\n\nQu'affiche ce programme ?",
          "options": [
            {
              "text": "`2`",
              "correct": true,
              "feedback": "Bonne réponse : au tour numéro 2, `trouve` devient vrai ; au\ntest suivant, `not trouve` est faux et la boucle s'arrête.\n"
            },
            {
              "text": "`3`",
              "correct": false,
              "feedback": "Erreur : la boucle s'arrête dès qu'une des deux conditions\ndevient fausse, ici `not trouve` après le tour numéro 2.\n"
            },
            {
              "text": "`1`",
              "correct": false,
              "feedback": "Erreur : après 1 tours, `essais` vaut 1 et `trouve` est\nencore faux, un tour de plus a lieu.\n"
            },
            {
              "text": "`0`",
              "correct": false,
              "feedback": "Erreur : au départ, les deux conditions sont vraies, la boucle\nfait au moins un tour.\n"
            }
          ],
          "explanation": "Avec `and`, la boucle continue seulement si toutes les conditions\nsont vraies. Elle s'arrête dès que l'une devient fausse : le nombre\nmaximal d'essais ou la réussite."
        },
        {
          "statement": "```python\nessais = 0\ntrouve = False\nwhile essais < 5 and not trouve:\n    essais = essais + 1\n    if essais == 3:\n        trouve = True\nprint(essais)\n```\n\nQu'affiche ce programme ?",
          "options": [
            {
              "text": "`3`",
              "correct": true,
              "feedback": "Bonne réponse : au tour numéro 3, `trouve` devient vrai ; au\ntest suivant, `not trouve` est faux et la boucle s'arrête.\n"
            },
            {
              "text": "`5`",
              "correct": false,
              "feedback": "Erreur : la boucle s'arrête dès qu'une des deux conditions\ndevient fausse, ici `not trouve` après le tour numéro 3.\n"
            },
            {
              "text": "`2`",
              "correct": false,
              "feedback": "Erreur : après 2 tours, `essais` vaut 2 et `trouve` est\nencore faux, un tour de plus a lieu.\n"
            },
            {
              "text": "`0`",
              "correct": false,
              "feedback": "Erreur : au départ, les deux conditions sont vraies, la boucle\nfait au moins un tour.\n"
            }
          ],
          "explanation": "Avec `and`, la boucle continue seulement si toutes les conditions\nsont vraies. Elle s'arrête dès que l'une devient fausse : le nombre\nmaximal d'essais ou la réussite."
        },
        {
          "statement": "```python\nessais = 0\ntrouve = False\nwhile essais < 6 and not trouve:\n    essais = essais + 1\n    if essais == 4:\n        trouve = True\nprint(essais)\n```\n\nQu'affiche ce programme ?",
          "options": [
            {
              "text": "`4`",
              "correct": true,
              "feedback": "Bonne réponse : au tour numéro 4, `trouve` devient vrai ; au\ntest suivant, `not trouve` est faux et la boucle s'arrête.\n"
            },
            {
              "text": "`6`",
              "correct": false,
              "feedback": "Erreur : la boucle s'arrête dès qu'une des deux conditions\ndevient fausse, ici `not trouve` après le tour numéro 4.\n"
            },
            {
              "text": "`3`",
              "correct": false,
              "feedback": "Erreur : après 3 tours, `essais` vaut 3 et `trouve` est\nencore faux, un tour de plus a lieu.\n"
            },
            {
              "text": "`0`",
              "correct": false,
              "feedback": "Erreur : au départ, les deux conditions sont vraies, la boucle\nfait au moins un tour.\n"
            }
          ],
          "explanation": "Avec `and`, la boucle continue seulement si toutes les conditions\nsont vraies. Elle s'arrête dès que l'une devient fausse : le nombre\nmaximal d'essais ou la réussite."
        }
      ]
    },
    {
      "id": "q11",
      "difficulty": 2,
      "skills": [
        "while",
        "trace"
      ],
      "title": "Décompte avant décollage",
      "statement": "```python\nn = 3\nwhile n > 0:\n    print(n)\n    n = n - 1\nprint(\"Décollage\")\n```\n\nQu'affiche ce programme ?",
      "options": [
        {
          "text": "3, 2, 1 puis `Décollage`",
          "correct": true,
          "feedback": "Bonne réponse : la boucle affiche puis diminue ; à 0, la\ncondition est fausse et le message final s'affiche.\n"
        },
        {
          "text": "3, 2, 1, 0 puis `Décollage`",
          "correct": false,
          "feedback": "Erreur : quand `n` vaut 0, `n > 0` est faux, rien n'est affiché\npar la boucle.\n"
        },
        {
          "text": "2, 1, 0 puis `Décollage`",
          "correct": false,
          "feedback": "Erreur : l'affichage a lieu avant la soustraction, on commence\npar 3.\n"
        },
        {
          "text": "`Décollage` seulement",
          "correct": false,
          "feedback": "Erreur : `3 > 0` est vrai, la boucle fait trois tours.\n"
        }
      ],
      "explanation": "L'ordre des instructions dans le bloc décide de ce qui est affiché :\nafficher puis diminuer donne 3, 2, 1 ; diminuer puis afficher\ndonnerait 2, 1, 0."
    },
    {
      "id": "q12",
      "difficulty": 3,
      "skills": [
        "boucle-infinie",
        "while"
      ],
      "title": "Une valeur jamais atteinte",
      "statement": "```python\nn = 0\nwhile n != 10:\n    n = n + 3\nprint(n)\n```\n\nQue fait ce programme ?",
      "options": [
        {
          "text": "Il ne s'arrête jamais, `n` saute par-dessus 10",
          "correct": true,
          "feedback": "Bonne réponse : `n` prend les valeurs 3, 6, 9, 12, 15… Il ne\nvaut jamais exactement 10, et `n != 10` reste vrai.\n"
        },
        {
          "text": "Il affiche 10, une fois cette valeur atteinte",
          "correct": false,
          "feedback": "Erreur : en avançant de 3 en 3 depuis 0, on passe de 9 à 12\nsans toucher 10.\n"
        },
        {
          "text": "Il affiche 12, première valeur au-delà de 10",
          "correct": false,
          "feedback": "Erreur : à 12, la condition `n != 10` est encore vraie, la\nboucle continue.\n"
        },
        {
          "text": "Il affiche 9, dernière valeur avant 10",
          "correct": false,
          "feedback": "Erreur : 9 est différent de 10, la boucle ne s'arrête pas là.\n"
        }
      ],
      "explanation": "Une condition en `!=` est dangereuse : si la valeur exacte n'est\njamais atteinte, la boucle est infinie. Une condition en `<` ou `<=`\ns'arrête dès que le seuil est dépassé."
    },
    {
      "id": "q13",
      "difficulty": 2,
      "skills": [
        "while",
        "accumulateur",
        "compteur"
      ],
      "title": "Une somme jusqu'à un seuil",
      "statement": "```python\ns = 0\nk = 1\nwhile s <= 10:\n    s = s + k\n    k = k + 1\nprint(k)\n```\n\nQu'affiche ce programme ?",
      "options": [
        {
          "text": "`6`",
          "correct": true,
          "feedback": "Bonne réponse : `s` passe par 1, 3, 6, 10 puis 15, et `k` est\naugmenté à chaque tour, 5 fois, de 1 à 6.\n"
        },
        {
          "text": "`5`",
          "correct": false,
          "feedback": "Erreur : à `s` égal à 10, la condition `s <= 10` est encore\nvraie, un tour de plus a lieu et `k` passe à 6.\n"
        },
        {
          "text": "`4`",
          "correct": false,
          "feedback": "Erreur : après 3 tours, `s` vaut 6, la boucle continue.\n"
        },
        {
          "text": "`15`",
          "correct": false,
          "feedback": "Erreur : 15 est la valeur finale de `s`, mais le programme\naffiche `k`.\n"
        }
      ],
      "explanation": "Deux variables évoluent ensemble : l'accumulateur `s` et le compteur\n`k`. Le `<=` inclut le cas d'égalité, ce qui peut ajouter un tour par\nrapport à `<`.",
      "variants": [
        {
          "statement": "```python\ns = 0\nk = 1\nwhile s <= 10:\n    s = s + k\n    k = k + 1\nprint(k)\n```\n\nQu'affiche ce programme ?",
          "options": [
            {
              "text": "`6`",
              "correct": true,
              "feedback": "Bonne réponse : `s` passe par 1, 3, 6, 10 puis 15, et `k` est\naugmenté à chaque tour, 5 fois, de 1 à 6.\n"
            },
            {
              "text": "`5`",
              "correct": false,
              "feedback": "Erreur : à `s` égal à 10, la condition `s <= 10` est encore\nvraie, un tour de plus a lieu et `k` passe à 6.\n"
            },
            {
              "text": "`4`",
              "correct": false,
              "feedback": "Erreur : après 3 tours, `s` vaut 6, la boucle continue.\n"
            },
            {
              "text": "`15`",
              "correct": false,
              "feedback": "Erreur : 15 est la valeur finale de `s`, mais le programme\naffiche `k`.\n"
            }
          ],
          "explanation": "Deux variables évoluent ensemble : l'accumulateur `s` et le compteur\n`k`. Le `<=` inclut le cas d'égalité, ce qui peut ajouter un tour par\nrapport à `<`."
        },
        {
          "statement": "```python\ns = 0\nk = 1\nwhile s <= 20:\n    s = s + k\n    k = k + 1\nprint(k)\n```\n\nQu'affiche ce programme ?",
          "options": [
            {
              "text": "`7`",
              "correct": true,
              "feedback": "Bonne réponse : `s` passe par 1, 3, 6, 10, 15 puis 21, et `k` est\naugmenté à chaque tour, 6 fois, de 1 à 7.\n"
            },
            {
              "text": "`6`",
              "correct": false,
              "feedback": "Erreur : à `s` égal à 15, la condition `s <= 20` est encore\nvraie, un tour de plus a lieu et `k` passe à 7.\n"
            },
            {
              "text": "`5`",
              "correct": false,
              "feedback": "Erreur : après 4 tours, `s` vaut 10, la boucle continue.\n"
            },
            {
              "text": "`21`",
              "correct": false,
              "feedback": "Erreur : 21 est la valeur finale de `s`, mais le programme\naffiche `k`.\n"
            }
          ],
          "explanation": "Deux variables évoluent ensemble : l'accumulateur `s` et le compteur\n`k`. Le `<=` inclut le cas d'égalité, ce qui peut ajouter un tour par\nrapport à `<`."
        },
        {
          "statement": "```python\ns = 0\nk = 1\nwhile s <= 5:\n    s = s + k\n    k = k + 1\nprint(k)\n```\n\nQu'affiche ce programme ?",
          "options": [
            {
              "text": "`4`",
              "correct": true,
              "feedback": "Bonne réponse : `s` passe par 1, 3 puis 6, et `k` est\naugmenté à chaque tour, 3 fois, de 1 à 4.\n"
            },
            {
              "text": "`3`",
              "correct": false,
              "feedback": "Erreur : à `s` égal à 3, la condition `s <= 5` est encore\nvraie, un tour de plus a lieu et `k` passe à 4.\n"
            },
            {
              "text": "`2`",
              "correct": false,
              "feedback": "Erreur : après 1 tours, `s` vaut 1, la boucle continue.\n"
            },
            {
              "text": "`6`",
              "correct": false,
              "feedback": "Erreur : 6 est la valeur finale de `s`, mais le programme\naffiche `k`.\n"
            }
          ],
          "explanation": "Deux variables évoluent ensemble : l'accumulateur `s` et le compteur\n`k`. Le `<=` inclut le cas d'égalité, ce qui peut ajouter un tour par\nrapport à `<`."
        }
      ]
    },
    {
      "id": "q14",
      "difficulty": 1,
      "skills": [
        "while",
        "condition-arret"
      ],
      "title": "Quand s'arrête un while",
      "statement": "Quand une boucle `while` s'arrête-t-elle ?",
      "options": [
        {
          "text": "Quand sa condition est fausse au moment du test, avant un tour",
          "correct": true,
          "feedback": "Bonne réponse : la condition est évaluée avant chaque tour ;\ndès qu'elle est fausse, le programme passe à la suite.\n"
        },
        {
          "text": "Après un nombre de tours fixé à l'avance dans l'en-tête",
          "correct": false,
          "feedback": "Erreur : c'est le principe de `for` avec `range`. Un `while`\nignore le nombre de tours à l'avance.\n"
        },
        {
          "text": "Quand la variable de la condition atteint 0",
          "correct": false,
          "feedback": "Erreur : la condition peut porter sur n'importe quelle valeur,\npas seulement sur 0.\n"
        },
        {
          "text": "Dès que sa condition devient vraie pendant un tour",
          "correct": false,
          "feedback": "Erreur : c'est l'inverse, une condition vraie fait continuer.\nEt le test n'a lieu qu'entre deux tours.\n"
        }
      ],
      "explanation": "Le `while` teste sa condition avant chaque tour, jamais au milieu.\nMême si la condition devient fausse au milieu d'un tour, le tour va\njusqu'au bout."
    },
    {
      "id": "q15",
      "difficulty": 2,
      "skills": [
        "while",
        "saisie"
      ],
      "title": "Redemander une saisie",
      "statement": "```python\nreponse = \"\"\nwhile reponse != \"oui\":\n    reponse = input(\"Continuer ? \")\nprint(\"Merci\")\n```\n\nL'utilisateur tape `non`, puis `Oui`, puis `oui`. Combien de fois la\nquestion est-elle posée ?",
      "options": [
        {
          "text": "3",
          "correct": true,
          "feedback": "Bonne réponse : `non` et `Oui` sont différents de `oui`, la\nboucle continue. La troisième réponse arrête la boucle.\n"
        },
        {
          "text": "2",
          "correct": false,
          "feedback": "Erreur : `Oui` avec une majuscule n'est pas égal à `oui`, la\nquestion est reposée.\n"
        },
        {
          "text": "1",
          "correct": false,
          "feedback": "Erreur : après `non`, la condition `reponse != \"oui\"` reste\nvraie.\n"
        },
        {
          "text": "Un nombre infini de fois",
          "correct": false,
          "feedback": "Erreur : la troisième saisie, `oui`, rend la condition fausse.\n"
        }
      ],
      "explanation": "Initialiser la variable à une valeur qui rend la condition vraie\npermet d'entrer dans la boucle une première fois. Ensuite, chaque\nsaisie est retestée jusqu'à la bonne."
    },
    {
      "id": "q16",
      "difficulty": 3,
      "skills": [
        "while",
        "trace",
        "deux-variables"
      ],
      "title": "Deux variables qui se croisent",
      "statement": "```python\na = 1\nb = 16\nwhile a < b:\n    a = a * 2\n    b = b - 2\nprint(a, b)\n```\n\nQu'affiche ce programme ?",
      "options": [
        {
          "text": "`16 8`",
          "correct": true,
          "feedback": "Bonne réponse : les couples successifs sont (2, 14), (4, 12), (8, 10) puis (16, 8). À ce\nmoment `a < b` est faux.\n"
        },
        {
          "text": "`8 10`",
          "correct": false,
          "feedback": "Erreur : 8 est encore inférieur à 10, un tour de plus a lieu.\n"
        },
        {
          "text": "`16 10`",
          "correct": false,
          "feedback": "Erreur : au dernier tour, `b` est aussi modifié et passe de 10 à\n8.\n"
        },
        {
          "text": "`32 6`",
          "correct": false,
          "feedback": "Erreur : à (16, 8), la condition est fausse, la boucle s'arrête.\n"
        }
      ],
      "explanation": "Quand deux variables changent dans le bloc, la trace se fait par\ncouples de valeurs, un couple par tour, jusqu'à celui qui rend la\ncondition fausse.",
      "variants": [
        {
          "statement": "```python\na = 1\nb = 16\nwhile a < b:\n    a = a * 2\n    b = b - 2\nprint(a, b)\n```\n\nQu'affiche ce programme ?",
          "options": [
            {
              "text": "`16 8`",
              "correct": true,
              "feedback": "Bonne réponse : les couples successifs sont (2, 14), (4, 12), (8, 10) puis (16, 8). À ce\nmoment `a < b` est faux.\n"
            },
            {
              "text": "`8 10`",
              "correct": false,
              "feedback": "Erreur : 8 est encore inférieur à 10, un tour de plus a lieu.\n"
            },
            {
              "text": "`16 10`",
              "correct": false,
              "feedback": "Erreur : au dernier tour, `b` est aussi modifié et passe de 10 à\n8.\n"
            },
            {
              "text": "`32 6`",
              "correct": false,
              "feedback": "Erreur : à (16, 8), la condition est fausse, la boucle s'arrête.\n"
            }
          ],
          "explanation": "Quand deux variables changent dans le bloc, la trace se fait par\ncouples de valeurs, un couple par tour, jusqu'à celui qui rend la\ncondition fausse."
        },
        {
          "statement": "```python\na = 3\nb = 40\nwhile a < b:\n    a = a * 2\n    b = b - 2\nprint(a, b)\n```\n\nQu'affiche ce programme ?",
          "options": [
            {
              "text": "`48 32`",
              "correct": true,
              "feedback": "Bonne réponse : les couples successifs sont (6, 38), (12, 36), (24, 34) puis (48, 32). À ce\nmoment `a < b` est faux.\n"
            },
            {
              "text": "`24 34`",
              "correct": false,
              "feedback": "Erreur : 24 est encore inférieur à 34, un tour de plus a lieu.\n"
            },
            {
              "text": "`48 34`",
              "correct": false,
              "feedback": "Erreur : au dernier tour, `b` est aussi modifié et passe de 34 à\n32.\n"
            },
            {
              "text": "`96 30`",
              "correct": false,
              "feedback": "Erreur : à (48, 32), la condition est fausse, la boucle s'arrête.\n"
            }
          ],
          "explanation": "Quand deux variables changent dans le bloc, la trace se fait par\ncouples de valeurs, un couple par tour, jusqu'à celui qui rend la\ncondition fausse."
        },
        {
          "statement": "```python\na = 1\nb = 24\nwhile a < b:\n    a = a * 2\n    b = b - 2\nprint(a, b)\n```\n\nQu'affiche ce programme ?",
          "options": [
            {
              "text": "`16 16`",
              "correct": true,
              "feedback": "Bonne réponse : les couples successifs sont (2, 22), (4, 20), (8, 18) puis (16, 16). À ce\nmoment `a < b` est faux.\n"
            },
            {
              "text": "`8 18`",
              "correct": false,
              "feedback": "Erreur : 8 est encore inférieur à 18, un tour de plus a lieu.\n"
            },
            {
              "text": "`16 18`",
              "correct": false,
              "feedback": "Erreur : au dernier tour, `b` est aussi modifié et passe de 18 à\n16.\n"
            },
            {
              "text": "`32 14`",
              "correct": false,
              "feedback": "Erreur : à (16, 16), la condition est fausse, la boucle s'arrête.\n"
            }
          ],
          "explanation": "Quand deux variables changent dans le bloc, la trace se fait par\ncouples de valeurs, un couple par tour, jusqu'à celui qui rend la\ncondition fausse."
        }
      ]
    },
    {
      "id": "q17",
      "difficulty": 2,
      "skills": [
        "while",
        "erreur"
      ],
      "title": "Une variable non initialisée",
      "statement": "```python\nwhile compteur < 10:\n    compteur = compteur + 1\nprint(compteur)\n```\n\nQue se passe-t-il ?",
      "options": [
        {
          "text": "Une erreur, `compteur` n'a pas de valeur au premier test",
          "correct": true,
          "feedback": "Bonne réponse : la condition lit `compteur` avant toute\naffectation, d'où une erreur `NameError`.\n"
        },
        {
          "text": "Dix tours, puis l'affichage de 10 après la boucle",
          "correct": false,
          "feedback": "Erreur : ce serait le cas avec `compteur = 0` avant la boucle.\n"
        },
        {
          "text": "Une boucle infinie, la condition reste vraie",
          "correct": false,
          "feedback": "Erreur : le programme s'arrête avant même le premier tour.\n"
        },
        {
          "text": "Aucun tour, la condition est fausse dès le départ",
          "correct": false,
          "feedback": "Erreur : la condition ne peut pas être évaluée du tout.\n"
        }
      ],
      "explanation": "Avant un `while`, on initialise les variables de la condition. C'est\nla première étape du schéma : initialiser, tester, modifier dans le\nbloc."
    },
    {
      "id": "q18",
      "difficulty": 3,
      "skills": [
        "while",
        "flottant",
        "compteur"
      ],
      "title": "Diviser jusqu'à passer sous un seuil",
      "statement": "```python\nx = 100\nn = 0\nwhile x > 1:\n    x = x / 2\n    n = n + 1\nprint(n)\n```\n\nQu'affiche ce programme ?",
      "options": [
        {
          "text": "`7`",
          "correct": true,
          "feedback": "Bonne réponse : `x` passe par 50.0, 25.0, 12.5, 6.25, 3.125, 1.5625 puis 0.78125, en 7 divisions.\n"
        },
        {
          "text": "`6`",
          "correct": false,
          "feedback": "Erreur : après 6 divisions, `x` vaut 1.5625, encore supérieur\nà 1.\n"
        },
        {
          "text": "`8`",
          "correct": false,
          "feedback": "Erreur : après 7 divisions, `x` est inférieur ou égal à 1 et la\nboucle s'arrête.\n"
        },
        {
          "text": "`100`",
          "correct": false,
          "feedback": "Erreur : le programme affiche le nombre de tours, pas la valeur\nde départ.\n"
        }
      ],
      "explanation": "La division `/` produit des flottants, et la condition `x > 1` finit\npar devenir fausse. Le compteur mesure le nombre de divisions\nnécessaires.",
      "variants": [
        {
          "statement": "```python\nx = 100\nn = 0\nwhile x > 1:\n    x = x / 2\n    n = n + 1\nprint(n)\n```\n\nQu'affiche ce programme ?",
          "options": [
            {
              "text": "`7`",
              "correct": true,
              "feedback": "Bonne réponse : `x` passe par 50.0, 25.0, 12.5, 6.25, 3.125, 1.5625 puis 0.78125, en 7 divisions.\n"
            },
            {
              "text": "`6`",
              "correct": false,
              "feedback": "Erreur : après 6 divisions, `x` vaut 1.5625, encore supérieur\nà 1.\n"
            },
            {
              "text": "`8`",
              "correct": false,
              "feedback": "Erreur : après 7 divisions, `x` est inférieur ou égal à 1 et la\nboucle s'arrête.\n"
            },
            {
              "text": "`100`",
              "correct": false,
              "feedback": "Erreur : le programme affiche le nombre de tours, pas la valeur\nde départ.\n"
            }
          ],
          "explanation": "La division `/` produit des flottants, et la condition `x > 1` finit\npar devenir fausse. Le compteur mesure le nombre de divisions\nnécessaires."
        },
        {
          "statement": "```python\nx = 1000\nn = 0\nwhile x > 1:\n    x = x / 2\n    n = n + 1\nprint(n)\n```\n\nQu'affiche ce programme ?",
          "options": [
            {
              "text": "`10`",
              "correct": true,
              "feedback": "Bonne réponse : `x` passe par 500.0, 250.0, 125.0, 62.5, 31.25, 15.625, 7.8125, 3.90625, 1.953125 puis 0.9765625, en 10 divisions.\n"
            },
            {
              "text": "`9`",
              "correct": false,
              "feedback": "Erreur : après 9 divisions, `x` vaut 1.953125, encore supérieur\nà 1.\n"
            },
            {
              "text": "`11`",
              "correct": false,
              "feedback": "Erreur : après 10 divisions, `x` est inférieur ou égal à 1 et la\nboucle s'arrête.\n"
            },
            {
              "text": "`1000`",
              "correct": false,
              "feedback": "Erreur : le programme affiche le nombre de tours, pas la valeur\nde départ.\n"
            }
          ],
          "explanation": "La division `/` produit des flottants, et la condition `x > 1` finit\npar devenir fausse. Le compteur mesure le nombre de divisions\nnécessaires."
        },
        {
          "statement": "```python\nx = 50\nn = 0\nwhile x > 1:\n    x = x / 2\n    n = n + 1\nprint(n)\n```\n\nQu'affiche ce programme ?",
          "options": [
            {
              "text": "`6`",
              "correct": true,
              "feedback": "Bonne réponse : `x` passe par 25.0, 12.5, 6.25, 3.125, 1.5625 puis 0.78125, en 6 divisions.\n"
            },
            {
              "text": "`5`",
              "correct": false,
              "feedback": "Erreur : après 5 divisions, `x` vaut 1.5625, encore supérieur\nà 1.\n"
            },
            {
              "text": "`7`",
              "correct": false,
              "feedback": "Erreur : après 6 divisions, `x` est inférieur ou égal à 1 et la\nboucle s'arrête.\n"
            },
            {
              "text": "`50`",
              "correct": false,
              "feedback": "Erreur : le programme affiche le nombre de tours, pas la valeur\nde départ.\n"
            }
          ],
          "explanation": "La division `/` produit des flottants, et la condition `x > 1` finit\npar devenir fausse. Le compteur mesure le nombre de divisions\nnécessaires."
        }
      ]
    },
    {
      "id": "q19",
      "difficulty": 3,
      "skills": [
        "while",
        "completer-code"
      ],
      "title": "Compléter pour que la boucle s'arrête",
      "statement": "```python\nniveau = 0\nwhile niveau < 5:\n    print(niveau)\n    ...\n```\n\nQuelle instruction, à la place des points, garantit l'arrêt de la\nboucle après cinq affichages ?",
      "options": [
        {
          "text": "`niveau = niveau + 1`",
          "correct": true,
          "feedback": "Bonne réponse : `niveau` augmente à chaque tour et atteint 5\naprès cinq affichages, ce qui rend la condition fausse.\n"
        },
        {
          "text": "`niveau + 1`",
          "correct": false,
          "feedback": "Erreur : ce calcul n'est rangé nulle part, `niveau` reste à 0 et\nla boucle est infinie.\n"
        },
        {
          "text": "`niveau = 0`",
          "correct": false,
          "feedback": "Erreur : remettre `niveau` à 0 empêche la condition de devenir\nfausse.\n"
        },
        {
          "text": "`print(niveau + 1)`",
          "correct": false,
          "feedback": "Erreur : afficher `niveau + 1` ne modifie pas `niveau`.\n"
        }
      ],
      "explanation": "Pour qu'un `while` s'arrête, le bloc doit modifier une variable de la\ncondition avec une affectation. Un calcul non affecté ne change\nrien."
    },
    {
      "id": "q20",
      "difficulty": 2,
      "skills": [
        "while",
        "division-entiere",
        "compteur"
      ],
      "title": "Compter les chiffres d'un nombre",
      "statement": "```python\nn = 4821\nc = 0\nwhile n > 0:\n    n = n // 10\n    c = c + 1\nprint(c)\n```\n\nQu'affiche ce programme ?",
      "options": [
        {
          "text": "`4`",
          "correct": true,
          "feedback": "Bonne réponse : `n` passe par 482, 48, 4 puis 0, soit 4\ndivisions, une par chiffre.\n"
        },
        {
          "text": "`3`",
          "correct": false,
          "feedback": "Erreur : à 4, la condition `n > 0` est encore vraie, un\ntour de plus donne 0.\n"
        },
        {
          "text": "`5`",
          "correct": false,
          "feedback": "Erreur : à 0, la boucle s'arrête, il n'y a pas de tour\nsupplémentaire.\n"
        },
        {
          "text": "`482`",
          "correct": false,
          "feedback": "Erreur : le programme affiche le compteur `c`, pas `n`.\n"
        }
      ],
      "explanation": "Diviser par 10 en division entière retire le dernier chiffre. Compter\nles divisions jusqu'à 0 revient à compter les chiffres du nombre.",
      "variants": [
        {
          "statement": "```python\nn = 4821\nc = 0\nwhile n > 0:\n    n = n // 10\n    c = c + 1\nprint(c)\n```\n\nQu'affiche ce programme ?",
          "options": [
            {
              "text": "`4`",
              "correct": true,
              "feedback": "Bonne réponse : `n` passe par 482, 48, 4 puis 0, soit 4\ndivisions, une par chiffre.\n"
            },
            {
              "text": "`3`",
              "correct": false,
              "feedback": "Erreur : à 4, la condition `n > 0` est encore vraie, un\ntour de plus donne 0.\n"
            },
            {
              "text": "`5`",
              "correct": false,
              "feedback": "Erreur : à 0, la boucle s'arrête, il n'y a pas de tour\nsupplémentaire.\n"
            },
            {
              "text": "`482`",
              "correct": false,
              "feedback": "Erreur : le programme affiche le compteur `c`, pas `n`.\n"
            }
          ],
          "explanation": "Diviser par 10 en division entière retire le dernier chiffre. Compter\nles divisions jusqu'à 0 revient à compter les chiffres du nombre."
        },
        {
          "statement": "```python\nn = 95\nc = 0\nwhile n > 0:\n    n = n // 10\n    c = c + 1\nprint(c)\n```\n\nQu'affiche ce programme ?",
          "options": [
            {
              "text": "`2`",
              "correct": true,
              "feedback": "Bonne réponse : `n` passe par 9 puis 0, soit 2\ndivisions, une par chiffre.\n"
            },
            {
              "text": "`1`",
              "correct": false,
              "feedback": "Erreur : à 9, la condition `n > 0` est encore vraie, un\ntour de plus donne 0.\n"
            },
            {
              "text": "`3`",
              "correct": false,
              "feedback": "Erreur : à 0, la boucle s'arrête, il n'y a pas de tour\nsupplémentaire.\n"
            },
            {
              "text": "`9`",
              "correct": false,
              "feedback": "Erreur : le programme affiche le compteur `c`, pas `n`.\n"
            }
          ],
          "explanation": "Diviser par 10 en division entière retire le dernier chiffre. Compter\nles divisions jusqu'à 0 revient à compter les chiffres du nombre."
        },
        {
          "statement": "```python\nn = 123456\nc = 0\nwhile n > 0:\n    n = n // 10\n    c = c + 1\nprint(c)\n```\n\nQu'affiche ce programme ?",
          "options": [
            {
              "text": "`6`",
              "correct": true,
              "feedback": "Bonne réponse : `n` passe par 12345, 1234, 123, 12, 1 puis 0, soit 6\ndivisions, une par chiffre.\n"
            },
            {
              "text": "`5`",
              "correct": false,
              "feedback": "Erreur : à 1, la condition `n > 0` est encore vraie, un\ntour de plus donne 0.\n"
            },
            {
              "text": "`7`",
              "correct": false,
              "feedback": "Erreur : à 0, la boucle s'arrête, il n'y a pas de tour\nsupplémentaire.\n"
            },
            {
              "text": "`12345`",
              "correct": false,
              "feedback": "Erreur : le programme affiche le compteur `c`, pas `n`.\n"
            }
          ],
          "explanation": "Diviser par 10 en division entière retire le dernier chiffre. Compter\nles divisions jusqu'à 0 revient à compter les chiffres du nombre."
        }
      ]
    },
    {
      "id": "q21",
      "difficulty": 1,
      "skills": [
        "while",
        "soustraction",
        "trace"
      ],
      "title": "Un compte à rebours de trois en trois",
      "statement": "Qu'affiche ce programme ?\n```python\ni = 10\nwhile i > 0:\n    i = i - 3\nprint(i)\n```",
      "options": [
        {
          "text": "`-2`",
          "correct": true,
          "feedback": "Bonne réponse : `i` descend de 3 en 3 tant qu'il est\nstrictement positif. Le dernier tour part de 1 et\naboutit à -2, qui arrête la boucle.\n"
        },
        {
          "text": "`1`",
          "correct": false,
          "feedback": "Erreur : 1 est encore strictement positif, donc un tour\nde plus a lieu.\n"
        },
        {
          "text": "`10`",
          "correct": false,
          "feedback": "Erreur : la condition `i > 0` est vraie au départ, la boucle\nmodifie bien `i`.\n"
        },
        {
          "text": "`7`",
          "correct": false,
          "feedback": "Erreur : 7 est la valeur après un seul tour, et la boucle\ncontinue tant que `i` reste positif.\n"
        }
      ],
      "explanation": "Un `while` continue tant que sa condition est vraie : il faut\nsuivre la variable jusqu'à ce que la condition devienne fausse.",
      "variants": [
        {
          "statement": "Qu'affiche ce programme ?\n```python\ni = 10\nwhile i > 0:\n    i = i - 3\nprint(i)\n```",
          "options": [
            {
              "text": "`-2`",
              "correct": true,
              "feedback": "Bonne réponse : `i` descend de 3 en 3 tant qu'il est\nstrictement positif. Le dernier tour part de 1 et\naboutit à -2, qui arrête la boucle.\n"
            },
            {
              "text": "`1`",
              "correct": false,
              "feedback": "Erreur : 1 est encore strictement positif, donc un tour\nde plus a lieu.\n"
            },
            {
              "text": "`10`",
              "correct": false,
              "feedback": "Erreur : la condition `i > 0` est vraie au départ, la boucle\nmodifie bien `i`.\n"
            },
            {
              "text": "`7`",
              "correct": false,
              "feedback": "Erreur : 7 est la valeur après un seul tour, et la boucle\ncontinue tant que `i` reste positif.\n"
            }
          ],
          "explanation": "Un `while` continue tant que sa condition est vraie : il faut\nsuivre la variable jusqu'à ce que la condition devienne fausse."
        },
        {
          "statement": "Qu'affiche ce programme ?\n```python\ni = 9\nwhile i > 0:\n    i = i - 3\nprint(i)\n```",
          "options": [
            {
              "text": "`0`",
              "correct": true,
              "feedback": "Bonne réponse : `i` descend de 3 en 3 tant qu'il est\nstrictement positif. Le dernier tour part de 3 et\naboutit à 0, qui arrête la boucle.\n"
            },
            {
              "text": "`3`",
              "correct": false,
              "feedback": "Erreur : 3 est encore strictement positif, donc un tour\nde plus a lieu.\n"
            },
            {
              "text": "`9`",
              "correct": false,
              "feedback": "Erreur : la condition `i > 0` est vraie au départ, la boucle\nmodifie bien `i`.\n"
            },
            {
              "text": "`6`",
              "correct": false,
              "feedback": "Erreur : 6 est la valeur après un seul tour, et la boucle\ncontinue tant que `i` reste positif.\n"
            }
          ],
          "explanation": "Un `while` continue tant que sa condition est vraie : il faut\nsuivre la variable jusqu'à ce que la condition devienne fausse."
        },
        {
          "statement": "Qu'affiche ce programme ?\n```python\ni = 8\nwhile i > 0:\n    i = i - 3\nprint(i)\n```",
          "options": [
            {
              "text": "`-1`",
              "correct": true,
              "feedback": "Bonne réponse : `i` descend de 3 en 3 tant qu'il est\nstrictement positif. Le dernier tour part de 2 et\naboutit à -1, qui arrête la boucle.\n"
            },
            {
              "text": "`2`",
              "correct": false,
              "feedback": "Erreur : 2 est encore strictement positif, donc un tour\nde plus a lieu.\n"
            },
            {
              "text": "`8`",
              "correct": false,
              "feedback": "Erreur : la condition `i > 0` est vraie au départ, la boucle\nmodifie bien `i`.\n"
            },
            {
              "text": "`5`",
              "correct": false,
              "feedback": "Erreur : 5 est la valeur après un seul tour, et la boucle\ncontinue tant que `i` reste positif.\n"
            }
          ],
          "explanation": "Un `while` continue tant que sa condition est vraie : il faut\nsuivre la variable jusqu'à ce que la condition devienne fausse."
        }
      ]
    },
    {
      "id": "q22",
      "difficulty": 1,
      "skills": [
        "while",
        "multiplication",
        "seuil"
      ],
      "title": "Multiplier par dix jusqu'à dépasser",
      "statement": "Qu'affiche ce programme ?\n```python\nx = 1\nwhile x < 800:\n    x = x * 10\nprint(x)\n```",
      "options": [
        {
          "text": "`1000`",
          "correct": true,
          "feedback": "Bonne réponse : `x` prend les valeurs 1, 10, 100, et ainsi de\nsuite, jusqu'à la première puissance de 10 qui atteint ou\ndépasse 800, soit 1000.\n"
        },
        {
          "text": "`800`",
          "correct": false,
          "feedback": "Erreur : `x` ne prend que des puissances de 10, il ne s'arrête\npas exactement sur 800.\n"
        },
        {
          "text": "`100`",
          "correct": false,
          "feedback": "Erreur : 100 est encore inférieur à 800, donc un tour de\nplus a lieu.\n"
        },
        {
          "text": "`1`",
          "correct": false,
          "feedback": "Erreur : la condition est vraie au départ, et `x` est multiplié\nau moins une fois.\n"
        }
      ],
      "explanation": "La boucle s'arrête dès que la condition devient fausse, c'est-à-dire\nà la première valeur qui atteint ou dépasse le seuil.",
      "variants": [
        {
          "statement": "Qu'affiche ce programme ?\n```python\nx = 1\nwhile x < 800:\n    x = x * 10\nprint(x)\n```",
          "options": [
            {
              "text": "`1000`",
              "correct": true,
              "feedback": "Bonne réponse : `x` prend les valeurs 1, 10, 100, et ainsi de\nsuite, jusqu'à la première puissance de 10 qui atteint ou\ndépasse 800, soit 1000.\n"
            },
            {
              "text": "`800`",
              "correct": false,
              "feedback": "Erreur : `x` ne prend que des puissances de 10, il ne s'arrête\npas exactement sur 800.\n"
            },
            {
              "text": "`100`",
              "correct": false,
              "feedback": "Erreur : 100 est encore inférieur à 800, donc un tour de\nplus a lieu.\n"
            },
            {
              "text": "`1`",
              "correct": false,
              "feedback": "Erreur : la condition est vraie au départ, et `x` est multiplié\nau moins une fois.\n"
            }
          ],
          "explanation": "La boucle s'arrête dès que la condition devient fausse, c'est-à-dire\nà la première valeur qui atteint ou dépasse le seuil."
        },
        {
          "statement": "Qu'affiche ce programme ?\n```python\nx = 1\nwhile x < 50:\n    x = x * 10\nprint(x)\n```",
          "options": [
            {
              "text": "`100`",
              "correct": true,
              "feedback": "Bonne réponse : `x` prend les valeurs 1, 10, 100, et ainsi de\nsuite, jusqu'à la première puissance de 10 qui atteint ou\ndépasse 50, soit 100.\n"
            },
            {
              "text": "`50`",
              "correct": false,
              "feedback": "Erreur : `x` ne prend que des puissances de 10, il ne s'arrête\npas exactement sur 50.\n"
            },
            {
              "text": "`10`",
              "correct": false,
              "feedback": "Erreur : 10 est encore inférieur à 50, donc un tour de\nplus a lieu.\n"
            },
            {
              "text": "`1`",
              "correct": false,
              "feedback": "Erreur : la condition est vraie au départ, et `x` est multiplié\nau moins une fois.\n"
            }
          ],
          "explanation": "La boucle s'arrête dès que la condition devient fausse, c'est-à-dire\nà la première valeur qui atteint ou dépasse le seuil."
        },
        {
          "statement": "Qu'affiche ce programme ?\n```python\nx = 1\nwhile x < 2500:\n    x = x * 10\nprint(x)\n```",
          "options": [
            {
              "text": "`10000`",
              "correct": true,
              "feedback": "Bonne réponse : `x` prend les valeurs 1, 10, 100, et ainsi de\nsuite, jusqu'à la première puissance de 10 qui atteint ou\ndépasse 2500, soit 10000.\n"
            },
            {
              "text": "`2500`",
              "correct": false,
              "feedback": "Erreur : `x` ne prend que des puissances de 10, il ne s'arrête\npas exactement sur 2500.\n"
            },
            {
              "text": "`1000`",
              "correct": false,
              "feedback": "Erreur : 1000 est encore inférieur à 2500, donc un tour de\nplus a lieu.\n"
            },
            {
              "text": "`1`",
              "correct": false,
              "feedback": "Erreur : la condition est vraie au départ, et `x` est multiplié\nau moins une fois.\n"
            }
          ],
          "explanation": "La boucle s'arrête dès que la condition devient fausse, c'est-à-dire\nà la première valeur qui atteint ou dépasse le seuil."
        }
      ]
    },
    {
      "id": "q23",
      "difficulty": 2,
      "skills": [
        "while",
        "multiple",
        "seuil"
      ],
      "title": "Le premier multiple au-delà d'un seuil",
      "statement": "Qu'affiche ce programme ?\n```python\nn = 0\nwhile n <= 50:\n    n = n + 7\nprint(n)\n```",
      "options": [
        {
          "text": "`56`",
          "correct": true,
          "feedback": "Bonne réponse : `n` parcourt les multiples de 7 et s'arrête au\npremier qui dépasse strictement 50, soit 56.\n"
        },
        {
          "text": "`49`",
          "correct": false,
          "feedback": "Erreur : 49 ne dépasse pas 50, la condition `n <= 50` est\nencore vraie et un tour de plus a lieu.\n"
        },
        {
          "text": "`50`",
          "correct": false,
          "feedback": "Erreur : `n` ne prend que des multiples de 7.\n"
        },
        {
          "text": "`7`",
          "correct": false,
          "feedback": "Erreur : 7 est la valeur après un seul tour, et la boucle\ncontinue tant que `n <= 50`.\n"
        }
      ],
      "explanation": "Ce schéma trouve le premier multiple d'un nombre qui dépasse un\nseuil : on avance pas à pas tant que le seuil n'est pas franchi.",
      "variants": [
        {
          "statement": "Qu'affiche ce programme ?\n```python\nn = 0\nwhile n <= 50:\n    n = n + 7\nprint(n)\n```",
          "options": [
            {
              "text": "`56`",
              "correct": true,
              "feedback": "Bonne réponse : `n` parcourt les multiples de 7 et s'arrête au\npremier qui dépasse strictement 50, soit 56.\n"
            },
            {
              "text": "`49`",
              "correct": false,
              "feedback": "Erreur : 49 ne dépasse pas 50, la condition `n <= 50` est\nencore vraie et un tour de plus a lieu.\n"
            },
            {
              "text": "`50`",
              "correct": false,
              "feedback": "Erreur : `n` ne prend que des multiples de 7.\n"
            },
            {
              "text": "`7`",
              "correct": false,
              "feedback": "Erreur : 7 est la valeur après un seul tour, et la boucle\ncontinue tant que `n <= 50`.\n"
            }
          ],
          "explanation": "Ce schéma trouve le premier multiple d'un nombre qui dépasse un\nseuil : on avance pas à pas tant que le seuil n'est pas franchi."
        },
        {
          "statement": "Qu'affiche ce programme ?\n```python\nn = 0\nwhile n <= 30:\n    n = n + 7\nprint(n)\n```",
          "options": [
            {
              "text": "`35`",
              "correct": true,
              "feedback": "Bonne réponse : `n` parcourt les multiples de 7 et s'arrête au\npremier qui dépasse strictement 30, soit 35.\n"
            },
            {
              "text": "`28`",
              "correct": false,
              "feedback": "Erreur : 28 ne dépasse pas 30, la condition `n <= 30` est\nencore vraie et un tour de plus a lieu.\n"
            },
            {
              "text": "`30`",
              "correct": false,
              "feedback": "Erreur : `n` ne prend que des multiples de 7.\n"
            },
            {
              "text": "`7`",
              "correct": false,
              "feedback": "Erreur : 7 est la valeur après un seul tour, et la boucle\ncontinue tant que `n <= 30`.\n"
            }
          ],
          "explanation": "Ce schéma trouve le premier multiple d'un nombre qui dépasse un\nseuil : on avance pas à pas tant que le seuil n'est pas franchi."
        },
        {
          "statement": "Qu'affiche ce programme ?\n```python\nn = 0\nwhile n <= 100:\n    n = n + 7\nprint(n)\n```",
          "options": [
            {
              "text": "`105`",
              "correct": true,
              "feedback": "Bonne réponse : `n` parcourt les multiples de 7 et s'arrête au\npremier qui dépasse strictement 100, soit 105.\n"
            },
            {
              "text": "`98`",
              "correct": false,
              "feedback": "Erreur : 98 ne dépasse pas 100, la condition `n <= 100` est\nencore vraie et un tour de plus a lieu.\n"
            },
            {
              "text": "`100`",
              "correct": false,
              "feedback": "Erreur : `n` ne prend que des multiples de 7.\n"
            },
            {
              "text": "`7`",
              "correct": false,
              "feedback": "Erreur : 7 est la valeur après un seul tour, et la boucle\ncontinue tant que `n <= 100`.\n"
            }
          ],
          "explanation": "Ce schéma trouve le premier multiple d'un nombre qui dépasse un\nseuil : on avance pas à pas tant que le seuil n'est pas franchi."
        }
      ]
    },
    {
      "id": "q24",
      "difficulty": 2,
      "skills": [
        "while",
        "compteur",
        "accumulateur"
      ],
      "title": "Combien de mois pour atteindre l'objectif",
      "statement": "Qu'affiche ce programme ?\n```python\nargent = 100\nmois = 0\nwhile argent < 150:\n    argent = argent + 12\n    mois = mois + 1\nprint(mois)\n```",
      "options": [
        {
          "text": "`5`",
          "correct": true,
          "feedback": "Bonne réponse : `argent` part de 100 et gagne 12 par tour. Il\nfaut 5 tours pour atteindre ou dépasser 150, et `mois` compte\nces tours.\n"
        },
        {
          "text": "`4`",
          "correct": false,
          "feedback": "Erreur : après 4 tours, `argent` est encore inférieur à 150,\nla boucle fait un tour de plus.\n"
        },
        {
          "text": "`6`",
          "correct": false,
          "feedback": "Erreur : dès que `argent` atteint 150, la condition `argent <\n150` est fausse et la boucle s'arrête.\n"
        },
        {
          "text": "`160`",
          "correct": false,
          "feedback": "Erreur : 160 est la valeur finale de `argent`, mais c'est\n`mois` qui est affiché.\n"
        }
      ],
      "explanation": "Deux variables évoluent ensemble : l'une avance vers l'objectif,\nl'autre compte les tours. Le `print` choisit laquelle afficher.",
      "variants": [
        {
          "statement": "Qu'affiche ce programme ?\n```python\nargent = 100\nmois = 0\nwhile argent < 150:\n    argent = argent + 12\n    mois = mois + 1\nprint(mois)\n```",
          "options": [
            {
              "text": "`5`",
              "correct": true,
              "feedback": "Bonne réponse : `argent` part de 100 et gagne 12 par tour. Il\nfaut 5 tours pour atteindre ou dépasser 150, et `mois` compte\nces tours.\n"
            },
            {
              "text": "`4`",
              "correct": false,
              "feedback": "Erreur : après 4 tours, `argent` est encore inférieur à 150,\nla boucle fait un tour de plus.\n"
            },
            {
              "text": "`6`",
              "correct": false,
              "feedback": "Erreur : dès que `argent` atteint 150, la condition `argent <\n150` est fausse et la boucle s'arrête.\n"
            },
            {
              "text": "`160`",
              "correct": false,
              "feedback": "Erreur : 160 est la valeur finale de `argent`, mais c'est\n`mois` qui est affiché.\n"
            }
          ],
          "explanation": "Deux variables évoluent ensemble : l'une avance vers l'objectif,\nl'autre compte les tours. Le `print` choisit laquelle afficher."
        },
        {
          "statement": "Qu'affiche ce programme ?\n```python\nargent = 100\nmois = 0\nwhile argent < 200:\n    argent = argent + 25\n    mois = mois + 1\nprint(mois)\n```",
          "options": [
            {
              "text": "`4`",
              "correct": true,
              "feedback": "Bonne réponse : `argent` part de 100 et gagne 25 par tour. Il\nfaut 4 tours pour atteindre ou dépasser 200, et `mois` compte\nces tours.\n"
            },
            {
              "text": "`3`",
              "correct": false,
              "feedback": "Erreur : après 3 tours, `argent` est encore inférieur à 200,\nla boucle fait un tour de plus.\n"
            },
            {
              "text": "`5`",
              "correct": false,
              "feedback": "Erreur : dès que `argent` atteint 200, la condition `argent <\n200` est fausse et la boucle s'arrête.\n"
            },
            {
              "text": "`200`",
              "correct": false,
              "feedback": "Erreur : 200 est la valeur finale de `argent`, mais c'est\n`mois` qui est affiché.\n"
            }
          ],
          "explanation": "Deux variables évoluent ensemble : l'une avance vers l'objectif,\nl'autre compte les tours. Le `print` choisit laquelle afficher."
        },
        {
          "statement": "Qu'affiche ce programme ?\n```python\nargent = 100\nmois = 0\nwhile argent < 130:\n    argent = argent + 15\n    mois = mois + 1\nprint(mois)\n```",
          "options": [
            {
              "text": "`2`",
              "correct": true,
              "feedback": "Bonne réponse : `argent` part de 100 et gagne 15 par tour. Il\nfaut 2 tours pour atteindre ou dépasser 130, et `mois` compte\nces tours.\n"
            },
            {
              "text": "`1`",
              "correct": false,
              "feedback": "Erreur : après 1 tours, `argent` est encore inférieur à 130,\nla boucle fait un tour de plus.\n"
            },
            {
              "text": "`3`",
              "correct": false,
              "feedback": "Erreur : dès que `argent` atteint 130, la condition `argent <\n130` est fausse et la boucle s'arrête.\n"
            },
            {
              "text": "`130`",
              "correct": false,
              "feedback": "Erreur : 130 est la valeur finale de `argent`, mais c'est\n`mois` qui est affiché.\n"
            }
          ],
          "explanation": "Deux variables évoluent ensemble : l'une avance vers l'objectif,\nl'autre compte les tours. Le `print` choisit laquelle afficher."
        }
      ]
    },
    {
      "id": "q25",
      "difficulty": 2,
      "skills": [
        "while",
        "print",
        "lignes"
      ],
      "title": "Des nombres pairs jusqu'à un seuil",
      "statement": "Combien de lignes ce programme affiche-t-il, et laquelle en dernier ?\n```python\nn = 0\nwhile n <= 6:\n    print(n)\n    n = n + 2\n```",
      "options": [
        {
          "text": "4 lignes, la dernière étant `6`",
          "correct": true,
          "feedback": "Bonne réponse : `n` prend les valeurs paires de 0 à 6,\nchacune affichée avant l'ajout de 2. Cela fait 4 lignes.\n"
        },
        {
          "text": "3 lignes, la dernière étant `6`",
          "correct": false,
          "feedback": "Erreur : la valeur 0 est affichée elle aussi, au premier tour.\n"
        },
        {
          "text": "6 lignes, la dernière étant `6`",
          "correct": false,
          "feedback": "Erreur : `n` avance de 2 en 2, il n'y a pas une ligne par\nentier.\n"
        },
        {
          "text": "Une infinité de lignes, la boucle ne s'arrêtant jamais",
          "correct": false,
          "feedback": "Erreur : `n` grandit à chaque tour et finit par dépasser 6.\n"
        }
      ],
      "explanation": "Pour compter les lignes, on liste les valeurs prises par la\nvariable : 0, 2, 4, et ainsi de suite tant que la condition tient.",
      "variants": [
        {
          "statement": "Combien de lignes ce programme affiche-t-il, et laquelle en dernier ?\n```python\nn = 0\nwhile n <= 6:\n    print(n)\n    n = n + 2\n```",
          "options": [
            {
              "text": "4 lignes, la dernière étant `6`",
              "correct": true,
              "feedback": "Bonne réponse : `n` prend les valeurs paires de 0 à 6,\nchacune affichée avant l'ajout de 2. Cela fait 4 lignes.\n"
            },
            {
              "text": "3 lignes, la dernière étant `6`",
              "correct": false,
              "feedback": "Erreur : la valeur 0 est affichée elle aussi, au premier tour.\n"
            },
            {
              "text": "6 lignes, la dernière étant `6`",
              "correct": false,
              "feedback": "Erreur : `n` avance de 2 en 2, il n'y a pas une ligne par\nentier.\n"
            },
            {
              "text": "Une infinité de lignes, la boucle ne s'arrêtant jamais",
              "correct": false,
              "feedback": "Erreur : `n` grandit à chaque tour et finit par dépasser 6.\n"
            }
          ],
          "explanation": "Pour compter les lignes, on liste les valeurs prises par la\nvariable : 0, 2, 4, et ainsi de suite tant que la condition tient."
        },
        {
          "statement": "Combien de lignes ce programme affiche-t-il, et laquelle en dernier ?\n```python\nn = 0\nwhile n <= 9:\n    print(n)\n    n = n + 2\n```",
          "options": [
            {
              "text": "5 lignes, la dernière étant `8`",
              "correct": true,
              "feedback": "Bonne réponse : `n` prend les valeurs paires de 0 à 8,\nchacune affichée avant l'ajout de 2. Cela fait 5 lignes.\n"
            },
            {
              "text": "4 lignes, la dernière étant `8`",
              "correct": false,
              "feedback": "Erreur : la valeur 0 est affichée elle aussi, au premier tour.\n"
            },
            {
              "text": "9 lignes, la dernière étant `9`",
              "correct": false,
              "feedback": "Erreur : `n` avance de 2 en 2, il n'y a pas une ligne par\nentier.\n"
            },
            {
              "text": "Une infinité de lignes, la boucle ne s'arrêtant jamais",
              "correct": false,
              "feedback": "Erreur : `n` grandit à chaque tour et finit par dépasser 9.\n"
            }
          ],
          "explanation": "Pour compter les lignes, on liste les valeurs prises par la\nvariable : 0, 2, 4, et ainsi de suite tant que la condition tient."
        },
        {
          "statement": "Combien de lignes ce programme affiche-t-il, et laquelle en dernier ?\n```python\nn = 0\nwhile n <= 4:\n    print(n)\n    n = n + 2\n```",
          "options": [
            {
              "text": "3 lignes, la dernière étant `4`",
              "correct": true,
              "feedback": "Bonne réponse : `n` prend les valeurs paires de 0 à 4,\nchacune affichée avant l'ajout de 2. Cela fait 3 lignes.\n"
            },
            {
              "text": "2 lignes, la dernière étant `4`",
              "correct": false,
              "feedback": "Erreur : la valeur 0 est affichée elle aussi, au premier tour.\n"
            },
            {
              "text": "4 lignes, la dernière étant `4`",
              "correct": false,
              "feedback": "Erreur : `n` avance de 2 en 2, il n'y a pas une ligne par\nentier.\n"
            },
            {
              "text": "Une infinité de lignes, la boucle ne s'arrêtant jamais",
              "correct": false,
              "feedback": "Erreur : `n` grandit à chaque tour et finit par dépasser 4.\n"
            }
          ],
          "explanation": "Pour compter les lignes, on liste les valeurs prises par la\nvariable : 0, 2, 4, et ainsi de suite tant que la condition tient."
        }
      ]
    },
    {
      "id": "q26",
      "difficulty": 3,
      "skills": [
        "while",
        "and",
        "trace"
      ],
      "title": "Deux conditions pour continuer",
      "statement": "Qu'affiche ce programme ?\n```python\ni = 0\ns = 0\nwhile i < 10 and s < 15:\n    s = s + i\n    i = i + 1\nprint(i, s)\n```",
      "options": [
        {
          "text": "`6 15`",
          "correct": true,
          "feedback": "Bonne réponse : la boucle continue tant que les deux conditions\nsont vraies. Elle s'arrête dès que `s` atteint 15, ou que `i`\natteint 10, selon ce qui arrive en premier.\n"
        },
        {
          "text": "`5 10`",
          "correct": false,
          "feedback": "Erreur : cet état correspond à un tour de moins. Vérifie que les\ndeux conditions sont encore vraies à ce moment.\n"
        },
        {
          "text": "`10 45`",
          "correct": false,
          "feedback": "Erreur : vérifie si la condition sur `s` arrête la boucle avant\nque `i` n'atteigne 10.\n"
        },
        {
          "text": "`7 21`",
          "correct": false,
          "feedback": "Erreur : cet état correspond à un tour de trop, la boucle\ns'arrête dès qu'une condition devient fausse.\n"
        }
      ],
      "explanation": "Avec `and`, la boucle s'arrête dès que l'une des deux conditions\ndevient fausse. Suivre `i` et `s` tour par tour est le seul moyen\nsûr de trouver l'état final.",
      "variants": [
        {
          "statement": "Qu'affiche ce programme ?\n```python\ni = 0\ns = 0\nwhile i < 10 and s < 15:\n    s = s + i\n    i = i + 1\nprint(i, s)\n```",
          "options": [
            {
              "text": "`6 15`",
              "correct": true,
              "feedback": "Bonne réponse : la boucle continue tant que les deux conditions\nsont vraies. Elle s'arrête dès que `s` atteint 15, ou que `i`\natteint 10, selon ce qui arrive en premier.\n"
            },
            {
              "text": "`5 10`",
              "correct": false,
              "feedback": "Erreur : cet état correspond à un tour de moins. Vérifie que les\ndeux conditions sont encore vraies à ce moment.\n"
            },
            {
              "text": "`10 45`",
              "correct": false,
              "feedback": "Erreur : vérifie si la condition sur `s` arrête la boucle avant\nque `i` n'atteigne 10.\n"
            },
            {
              "text": "`7 21`",
              "correct": false,
              "feedback": "Erreur : cet état correspond à un tour de trop, la boucle\ns'arrête dès qu'une condition devient fausse.\n"
            }
          ],
          "explanation": "Avec `and`, la boucle s'arrête dès que l'une des deux conditions\ndevient fausse. Suivre `i` et `s` tour par tour est le seul moyen\nsûr de trouver l'état final."
        },
        {
          "statement": "Qu'affiche ce programme ?\n```python\ni = 0\ns = 0\nwhile i < 10 and s < 4:\n    s = s + i\n    i = i + 1\nprint(i, s)\n```",
          "options": [
            {
              "text": "`4 6`",
              "correct": true,
              "feedback": "Bonne réponse : la boucle continue tant que les deux conditions\nsont vraies. Elle s'arrête dès que `s` atteint 4, ou que `i`\natteint 10, selon ce qui arrive en premier.\n"
            },
            {
              "text": "`3 3`",
              "correct": false,
              "feedback": "Erreur : cet état correspond à un tour de moins. Vérifie que les\ndeux conditions sont encore vraies à ce moment.\n"
            },
            {
              "text": "`10 45`",
              "correct": false,
              "feedback": "Erreur : vérifie si la condition sur `s` arrête la boucle avant\nque `i` n'atteigne 10.\n"
            },
            {
              "text": "`5 10`",
              "correct": false,
              "feedback": "Erreur : cet état correspond à un tour de trop, la boucle\ns'arrête dès qu'une condition devient fausse.\n"
            }
          ],
          "explanation": "Avec `and`, la boucle s'arrête dès que l'une des deux conditions\ndevient fausse. Suivre `i` et `s` tour par tour est le seul moyen\nsûr de trouver l'état final."
        },
        {
          "statement": "Qu'affiche ce programme ?\n```python\ni = 0\ns = 0\nwhile i < 10 and s < 100:\n    s = s + i\n    i = i + 1\nprint(i, s)\n```",
          "options": [
            {
              "text": "`10 45`",
              "correct": true,
              "feedback": "Bonne réponse : la boucle continue tant que les deux conditions\nsont vraies. Elle s'arrête dès que `s` atteint 100, ou que `i`\natteint 10, selon ce qui arrive en premier.\n"
            },
            {
              "text": "`9 36`",
              "correct": false,
              "feedback": "Erreur : cet état correspond à un tour de moins. Vérifie que les\ndeux conditions sont encore vraies à ce moment.\n"
            },
            {
              "text": "`11 55`",
              "correct": false,
              "feedback": "Erreur : vérifie si la condition sur `s` arrête la boucle avant\nque `i` n'atteigne 10.\n"
            },
            {
              "text": "`6 15`",
              "correct": false,
              "feedback": "Erreur : cet état correspond à un tour de trop, la boucle\ns'arrête dès qu'une condition devient fausse.\n"
            }
          ],
          "explanation": "Avec `and`, la boucle s'arrête dès que l'une des deux conditions\ndevient fausse. Suivre `i` et `s` tour par tour est le seul moyen\nsûr de trouver l'état final."
        }
      ]
    },
    {
      "id": "q27",
      "difficulty": 3,
      "skills": [
        "while",
        "accumulateur",
        "compteur"
      ],
      "title": "Additionner jusqu'à un seuil",
      "statement": "Qu'affiche ce programme ?\n```python\ns = 0\ni = 1\nwhile s < 20:\n    s = s + i\n    i = i + 1\nprint(i)\n```",
      "options": [
        {
          "text": "`7`",
          "correct": true,
          "feedback": "Bonne réponse : `s` cumule 1, 2, 3, et ainsi de suite jusqu'à\natteindre 21, qui dépasse 20. `i` a alors été incrémenté une\nfois de plus que la dernière valeur ajoutée, 6, d'où 7.\n"
        },
        {
          "text": "`6`",
          "correct": false,
          "feedback": "Erreur : 6 est la dernière valeur ajoutée à `s`, mais `i`\nest incrémenté juste après l'ajout.\n"
        },
        {
          "text": "`21`",
          "correct": false,
          "feedback": "Erreur : 21 est la valeur finale de `s`, alors que c'est `i`\nqui est affiché.\n"
        },
        {
          "text": "`20`",
          "correct": false,
          "feedback": "Erreur : 20 est le seuil, ni `i` ni `s` ne s'y arrêtent\nexactement.\n"
        }
      ],
      "explanation": "Quand deux variables évoluent dans une boucle, l'ordre des\ninstructions compte : ici `i` est modifié après avoir servi.",
      "variants": [
        {
          "statement": "Qu'affiche ce programme ?\n```python\ns = 0\ni = 1\nwhile s < 20:\n    s = s + i\n    i = i + 1\nprint(i)\n```",
          "options": [
            {
              "text": "`7`",
              "correct": true,
              "feedback": "Bonne réponse : `s` cumule 1, 2, 3, et ainsi de suite jusqu'à\natteindre 21, qui dépasse 20. `i` a alors été incrémenté une\nfois de plus que la dernière valeur ajoutée, 6, d'où 7.\n"
            },
            {
              "text": "`6`",
              "correct": false,
              "feedback": "Erreur : 6 est la dernière valeur ajoutée à `s`, mais `i`\nest incrémenté juste après l'ajout.\n"
            },
            {
              "text": "`21`",
              "correct": false,
              "feedback": "Erreur : 21 est la valeur finale de `s`, alors que c'est `i`\nqui est affiché.\n"
            },
            {
              "text": "`20`",
              "correct": false,
              "feedback": "Erreur : 20 est le seuil, ni `i` ni `s` ne s'y arrêtent\nexactement.\n"
            }
          ],
          "explanation": "Quand deux variables évoluent dans une boucle, l'ordre des\ninstructions compte : ici `i` est modifié après avoir servi."
        },
        {
          "statement": "Qu'affiche ce programme ?\n```python\ns = 0\ni = 1\nwhile s < 12:\n    s = s + i\n    i = i + 1\nprint(i)\n```",
          "options": [
            {
              "text": "`6`",
              "correct": true,
              "feedback": "Bonne réponse : `s` cumule 1, 2, 3, et ainsi de suite jusqu'à\natteindre 15, qui dépasse 12. `i` a alors été incrémenté une\nfois de plus que la dernière valeur ajoutée, 5, d'où 6.\n"
            },
            {
              "text": "`5`",
              "correct": false,
              "feedback": "Erreur : 5 est la dernière valeur ajoutée à `s`, mais `i`\nest incrémenté juste après l'ajout.\n"
            },
            {
              "text": "`15`",
              "correct": false,
              "feedback": "Erreur : 15 est la valeur finale de `s`, alors que c'est `i`\nqui est affiché.\n"
            },
            {
              "text": "`12`",
              "correct": false,
              "feedback": "Erreur : 12 est le seuil, ni `i` ni `s` ne s'y arrêtent\nexactement.\n"
            }
          ],
          "explanation": "Quand deux variables évoluent dans une boucle, l'ordre des\ninstructions compte : ici `i` est modifié après avoir servi."
        },
        {
          "statement": "Qu'affiche ce programme ?\n```python\ns = 0\ni = 1\nwhile s < 30:\n    s = s + i\n    i = i + 1\nprint(i)\n```",
          "options": [
            {
              "text": "`9`",
              "correct": true,
              "feedback": "Bonne réponse : `s` cumule 1, 2, 3, et ainsi de suite jusqu'à\natteindre 36, qui dépasse 30. `i` a alors été incrémenté une\nfois de plus que la dernière valeur ajoutée, 8, d'où 9.\n"
            },
            {
              "text": "`8`",
              "correct": false,
              "feedback": "Erreur : 8 est la dernière valeur ajoutée à `s`, mais `i`\nest incrémenté juste après l'ajout.\n"
            },
            {
              "text": "`36`",
              "correct": false,
              "feedback": "Erreur : 36 est la valeur finale de `s`, alors que c'est `i`\nqui est affiché.\n"
            },
            {
              "text": "`30`",
              "correct": false,
              "feedback": "Erreur : 30 est le seuil, ni `i` ni `s` ne s'y arrêtent\nexactement.\n"
            }
          ],
          "explanation": "Quand deux variables évoluent dans une boucle, l'ordre des\ninstructions compte : ici `i` est modifié après avoir servi."
        }
      ]
    },
    {
      "id": "q28",
      "difficulty": 3,
      "skills": [
        "while",
        "chaine",
        "indice",
        "compteur"
      ],
      "title": "Compter une lettre avec un indice",
      "statement": "Qu'affiche ce programme ?\n```python\nmot = \"anaconda\"\ni = 0\nc = 0\nwhile i < len(mot):\n    if mot[i] == \"a\":\n        c = c + 1\n    i = i + 1\nprint(c)\n```",
      "options": [
        {
          "text": "`3`",
          "correct": true,
          "feedback": "Bonne réponse : `i` parcourt les indices de 0 à 7, et `c`\nest incrémenté à chaque lettre `a` rencontrée, soit 3 fois.\n"
        },
        {
          "text": "`8`",
          "correct": false,
          "feedback": "Erreur : 8 est la longueur du mot, le nombre de tours, pas le\nnombre de lettres `a`.\n"
        },
        {
          "text": "`0`",
          "correct": false,
          "feedback": "Erreur : 0 est l'indice de la première lettre `a`,\nmais le programme compte les occurrences.\n"
        },
        {
          "text": "`5`",
          "correct": false,
          "feedback": "Erreur : 5 est le nombre de lettres différentes de\n`a`, le `if` compte l'inverse.\n"
        }
      ],
      "explanation": "Un `while` avec un indice parcourt une chaîne caractère par\ncaractère. Le compteur n'avance que quand la condition est vraie.",
      "variants": [
        {
          "statement": "Qu'affiche ce programme ?\n```python\nmot = \"anaconda\"\ni = 0\nc = 0\nwhile i < len(mot):\n    if mot[i] == \"a\":\n        c = c + 1\n    i = i + 1\nprint(c)\n```",
          "options": [
            {
              "text": "`3`",
              "correct": true,
              "feedback": "Bonne réponse : `i` parcourt les indices de 0 à 7, et `c`\nest incrémenté à chaque lettre `a` rencontrée, soit 3 fois.\n"
            },
            {
              "text": "`8`",
              "correct": false,
              "feedback": "Erreur : 8 est la longueur du mot, le nombre de tours, pas le\nnombre de lettres `a`.\n"
            },
            {
              "text": "`0`",
              "correct": false,
              "feedback": "Erreur : 0 est l'indice de la première lettre `a`,\nmais le programme compte les occurrences.\n"
            },
            {
              "text": "`5`",
              "correct": false,
              "feedback": "Erreur : 5 est le nombre de lettres différentes de\n`a`, le `if` compte l'inverse.\n"
            }
          ],
          "explanation": "Un `while` avec un indice parcourt une chaîne caractère par\ncaractère. Le compteur n'avance que quand la condition est vraie."
        },
        {
          "statement": "Qu'affiche ce programme ?\n```python\nmot = \"mississippi\"\ni = 0\nc = 0\nwhile i < len(mot):\n    if mot[i] == \"s\":\n        c = c + 1\n    i = i + 1\nprint(c)\n```",
          "options": [
            {
              "text": "`4`",
              "correct": true,
              "feedback": "Bonne réponse : `i` parcourt les indices de 0 à 10, et `c`\nest incrémenté à chaque lettre `s` rencontrée, soit 4 fois.\n"
            },
            {
              "text": "`11`",
              "correct": false,
              "feedback": "Erreur : 11 est la longueur du mot, le nombre de tours, pas le\nnombre de lettres `s`.\n"
            },
            {
              "text": "`2`",
              "correct": false,
              "feedback": "Erreur : 2 est l'indice de la première lettre `s`,\nmais le programme compte les occurrences.\n"
            },
            {
              "text": "`7`",
              "correct": false,
              "feedback": "Erreur : 7 est le nombre de lettres différentes de\n`s`, le `if` compte l'inverse.\n"
            }
          ],
          "explanation": "Un `while` avec un indice parcourt une chaîne caractère par\ncaractère. Le compteur n'avance que quand la condition est vraie."
        },
        {
          "statement": "Qu'affiche ce programme ?\n```python\nmot = \"python\"\ni = 0\nc = 0\nwhile i < len(mot):\n    if mot[i] == \"t\":\n        c = c + 1\n    i = i + 1\nprint(c)\n```",
          "options": [
            {
              "text": "`1`",
              "correct": true,
              "feedback": "Bonne réponse : `i` parcourt les indices de 0 à 5, et `c`\nest incrémenté à chaque lettre `t` rencontrée, soit 1 fois.\n"
            },
            {
              "text": "`6`",
              "correct": false,
              "feedback": "Erreur : 6 est la longueur du mot, le nombre de tours, pas le\nnombre de lettres `t`.\n"
            },
            {
              "text": "`2`",
              "correct": false,
              "feedback": "Erreur : 2 est l'indice de la première lettre `t`,\nmais le programme compte les occurrences.\n"
            },
            {
              "text": "`5`",
              "correct": false,
              "feedback": "Erreur : 5 est le nombre de lettres différentes de\n`t`, le `if` compte l'inverse.\n"
            }
          ],
          "explanation": "Un `while` avec un indice parcourt une chaîne caractère par\ncaractère. Le compteur n'avance que quand la condition est vraie."
        }
      ]
    },
    {
      "id": "q29",
      "difficulty": 3,
      "skills": [
        "while",
        "for",
        "equivalence"
      ],
      "title": "La même boucle avec while",
      "statement": "Quelle boucle `while` affiche exactement ce que produit\n`for i in range(5): print(i)` ?",
      "options": [
        {
          "text": "```python\ni = 0\nwhile i < 5:\n    print(i)\n    i = i + 1\n```",
          "correct": true,
          "feedback": "Bonne réponse : `i` part de 0, est affiché puis incrémenté, et la\nboucle s'arrête avant 5. Les valeurs 0 à 4 sont affichées.\n"
        },
        {
          "text": "```python\ni = 1\nwhile i <= 5:\n    print(i)\n    i = i + 1\n```",
          "correct": false,
          "feedback": "Erreur : cette boucle affiche 1 à 5, alors que `range(5)`\ncommence à 0 et s'arrête à 4.\n"
        },
        {
          "text": "```python\ni = 0\nwhile i <= 5:\n    print(i)\n    i = i + 1\n```",
          "correct": false,
          "feedback": "Erreur : avec `<=`, la valeur 5 est affichée, ce que `range(5)`\nne fait pas.\n"
        },
        {
          "text": "```python\ni = 0\nwhile i < 5:\n    i = i + 1\n    print(i)\n```",
          "correct": false,
          "feedback": "Erreur : incrémenter avant d'afficher décale tout : cette boucle\naffiche 1 à 5.\n"
        }
      ],
      "explanation": "Toute boucle `for` sur un `range` se réécrit en `while` avec une\nvariable initialisée, une condition et une incrémentation. L'ordre\ndes instructions dans le corps change le résultat."
    },
    {
      "id": "q30",
      "difficulty": 3,
      "skills": [
        "while",
        "doublement",
        "compteur"
      ],
      "title": "Compter les doublements",
      "statement": "Qu'affiche ce programme ?\n```python\ne = 1\nn = 0\nwhile e < 1000:\n    e = e * 2\n    n = n + 1\nprint(n)\n```",
      "options": [
        {
          "text": "`10`",
          "correct": true,
          "feedback": "Bonne réponse : `e` double à chaque tour et `n` compte les\ntours. Il faut 10 doublements pour que `e` atteigne 1024, la\npremière puissance de 2 qui vaut au moins 1000.\n"
        },
        {
          "text": "`1024`",
          "correct": false,
          "feedback": "Erreur : 1024 est la valeur finale de `e`, mais le programme\naffiche `n`.\n"
        },
        {
          "text": "`9`",
          "correct": false,
          "feedback": "Erreur : après 9 doublements, `e` est encore inférieur à 1000,\nun tour de plus a lieu.\n"
        },
        {
          "text": "`1000`",
          "correct": false,
          "feedback": "Erreur : 1000 est le seuil, pas le nombre de tours.\n"
        }
      ],
      "explanation": "Ce programme répond à la question « combien de fois faut-il doubler\npour dépasser un seuil ? ». Le compteur `n` en garde la trace.",
      "variants": [
        {
          "statement": "Qu'affiche ce programme ?\n```python\ne = 1\nn = 0\nwhile e < 1000:\n    e = e * 2\n    n = n + 1\nprint(n)\n```",
          "options": [
            {
              "text": "`10`",
              "correct": true,
              "feedback": "Bonne réponse : `e` double à chaque tour et `n` compte les\ntours. Il faut 10 doublements pour que `e` atteigne 1024, la\npremière puissance de 2 qui vaut au moins 1000.\n"
            },
            {
              "text": "`1024`",
              "correct": false,
              "feedback": "Erreur : 1024 est la valeur finale de `e`, mais le programme\naffiche `n`.\n"
            },
            {
              "text": "`9`",
              "correct": false,
              "feedback": "Erreur : après 9 doublements, `e` est encore inférieur à 1000,\nun tour de plus a lieu.\n"
            },
            {
              "text": "`1000`",
              "correct": false,
              "feedback": "Erreur : 1000 est le seuil, pas le nombre de tours.\n"
            }
          ],
          "explanation": "Ce programme répond à la question « combien de fois faut-il doubler\npour dépasser un seuil ? ». Le compteur `n` en garde la trace."
        },
        {
          "statement": "Qu'affiche ce programme ?\n```python\ne = 1\nn = 0\nwhile e < 100:\n    e = e * 2\n    n = n + 1\nprint(n)\n```",
          "options": [
            {
              "text": "`7`",
              "correct": true,
              "feedback": "Bonne réponse : `e` double à chaque tour et `n` compte les\ntours. Il faut 7 doublements pour que `e` atteigne 128, la\npremière puissance de 2 qui vaut au moins 100.\n"
            },
            {
              "text": "`128`",
              "correct": false,
              "feedback": "Erreur : 128 est la valeur finale de `e`, mais le programme\naffiche `n`.\n"
            },
            {
              "text": "`6`",
              "correct": false,
              "feedback": "Erreur : après 6 doublements, `e` est encore inférieur à 100,\nun tour de plus a lieu.\n"
            },
            {
              "text": "`100`",
              "correct": false,
              "feedback": "Erreur : 100 est le seuil, pas le nombre de tours.\n"
            }
          ],
          "explanation": "Ce programme répond à la question « combien de fois faut-il doubler\npour dépasser un seuil ? ». Le compteur `n` en garde la trace."
        },
        {
          "statement": "Qu'affiche ce programme ?\n```python\ne = 1\nn = 0\nwhile e < 50:\n    e = e * 2\n    n = n + 1\nprint(n)\n```",
          "options": [
            {
              "text": "`6`",
              "correct": true,
              "feedback": "Bonne réponse : `e` double à chaque tour et `n` compte les\ntours. Il faut 6 doublements pour que `e` atteigne 64, la\npremière puissance de 2 qui vaut au moins 50.\n"
            },
            {
              "text": "`64`",
              "correct": false,
              "feedback": "Erreur : 64 est la valeur finale de `e`, mais le programme\naffiche `n`.\n"
            },
            {
              "text": "`5`",
              "correct": false,
              "feedback": "Erreur : après 5 doublements, `e` est encore inférieur à 50,\nun tour de plus a lieu.\n"
            },
            {
              "text": "`50`",
              "correct": false,
              "feedback": "Erreur : 50 est le seuil, pas le nombre de tours.\n"
            }
          ],
          "explanation": "Ce programme répond à la question « combien de fois faut-il doubler\npour dépasser un seuil ? ». Le compteur `n` en garde la trace."
        }
      ]
    }
  ]
}