{
  "chapter": {
    "id": "python-boucles-for",
    "level": "snt",
    "theme": "Programmation",
    "title": "5. Boucles bornées : for",
    "description": "La boucle for et la fonction range, avec un, deux ou trois arguments ;\nle nombre de tours et les valeurs prises par la variable de boucle ;\nles schémas de l'accumulateur et du compteur ; le parcours d'une\nchaîne de caractères ; les boucles imbriquées.",
    "prerequisites": [],
    "references": []
  },
  "questions": [
    {
      "id": "q01",
      "difficulty": 1,
      "skills": [
        "for",
        "range"
      ],
      "title": "Les valeurs de range",
      "statement": "```python\nfor i in range(4):\n    print(i)\n```\n\nQuelles valeurs sont affichées ?",
      "options": [
        {
          "text": "0, 1, 2 et 3",
          "correct": true,
          "feedback": "Bonne réponse : `range(4)` fournit quatre entiers, de 0 à 3. La\nvaleur 4 n'en fait pas partie.\n"
        },
        {
          "text": "1, 2, 3 et 4",
          "correct": false,
          "feedback": "Erreur : `range` commence à 0 quand on ne lui donne qu'un\nargument.\n"
        },
        {
          "text": "0, 1, 2, 3 et 4",
          "correct": false,
          "feedback": "Erreur : ce serait cinq valeurs. `range(4)` s'arrête avant 4.\n"
        },
        {
          "text": "Quatre fois le nombre 4",
          "correct": false,
          "feedback": "Erreur : `i` change à chaque tour, il prend les valeurs\nsuccessives fournies par `range`.\n"
        }
      ],
      "explanation": "`range(n)` produit les entiers de 0 à `n - 1`, soit `n` valeurs. La\nvariable de boucle les prend une à une, dans l'ordre."
    },
    {
      "id": "q02",
      "difficulty": 1,
      "skills": [
        "range",
        "tours"
      ],
      "title": "Combien de pas",
      "statement": "Un robot avance d'un pas à chaque tour de boucle.\n\n```python\nfor k in range(2, 7):\n    avancer()\n```\n\nCombien de pas fait-il ?",
      "options": [
        {
          "text": "5",
          "correct": true,
          "feedback": "Bonne réponse : `k` prend les valeurs 2, 3, 4, 5 et 6, soit 5\ntours. Le nombre de tours vaut 7 moins 2.\n"
        },
        {
          "text": "6",
          "correct": false,
          "feedback": "Erreur : la borne 7 est exclue, la dernière valeur est 6.\n"
        },
        {
          "text": "7",
          "correct": false,
          "feedback": "Erreur : la boucle ne part pas de 0 mais de 2, et s'arrête avant\n7.\n"
        },
        {
          "text": "4",
          "correct": false,
          "feedback": "Erreur : de 2 à 6 inclus, il y a 5 valeurs.\n"
        }
      ],
      "explanation": "`range(a, b)` fournit les entiers de `a` inclus à `b` exclu, soit\n`b - a` valeurs. Le nombre de tours ne dépend pas de ce que fait le\ncorps de la boucle.",
      "variants": [
        {
          "statement": "Un robot avance d'un pas à chaque tour de boucle.\n\n```python\nfor k in range(2, 7):\n    avancer()\n```\n\nCombien de pas fait-il ?",
          "options": [
            {
              "text": "5",
              "correct": true,
              "feedback": "Bonne réponse : `k` prend les valeurs 2, 3, 4, 5 et 6, soit 5\ntours. Le nombre de tours vaut 7 moins 2.\n"
            },
            {
              "text": "6",
              "correct": false,
              "feedback": "Erreur : la borne 7 est exclue, la dernière valeur est 6.\n"
            },
            {
              "text": "7",
              "correct": false,
              "feedback": "Erreur : la boucle ne part pas de 0 mais de 2, et s'arrête avant\n7.\n"
            },
            {
              "text": "4",
              "correct": false,
              "feedback": "Erreur : de 2 à 6 inclus, il y a 5 valeurs.\n"
            }
          ],
          "explanation": "`range(a, b)` fournit les entiers de `a` inclus à `b` exclu, soit\n`b - a` valeurs. Le nombre de tours ne dépend pas de ce que fait le\ncorps de la boucle."
        },
        {
          "statement": "Un robot avance d'un pas à chaque tour de boucle.\n\n```python\nfor k in range(3, 11):\n    avancer()\n```\n\nCombien de pas fait-il ?",
          "options": [
            {
              "text": "8",
              "correct": true,
              "feedback": "Bonne réponse : `k` prend les valeurs 3, 4, 5, 6, 7, 8, 9 et 10, soit 8\ntours. Le nombre de tours vaut 11 moins 3.\n"
            },
            {
              "text": "9",
              "correct": false,
              "feedback": "Erreur : la borne 11 est exclue, la dernière valeur est 10.\n"
            },
            {
              "text": "11",
              "correct": false,
              "feedback": "Erreur : la boucle ne part pas de 0 mais de 3, et s'arrête avant\n11.\n"
            },
            {
              "text": "7",
              "correct": false,
              "feedback": "Erreur : de 3 à 10 inclus, il y a 8 valeurs.\n"
            }
          ],
          "explanation": "`range(a, b)` fournit les entiers de `a` inclus à `b` exclu, soit\n`b - a` valeurs. Le nombre de tours ne dépend pas de ce que fait le\ncorps de la boucle."
        },
        {
          "statement": "Un robot avance d'un pas à chaque tour de boucle.\n\n```python\nfor k in range(5, 9):\n    avancer()\n```\n\nCombien de pas fait-il ?",
          "options": [
            {
              "text": "4",
              "correct": true,
              "feedback": "Bonne réponse : `k` prend les valeurs 5, 6, 7 et 8, soit 4\ntours. Le nombre de tours vaut 9 moins 5.\n"
            },
            {
              "text": "5",
              "correct": false,
              "feedback": "Erreur : la borne 9 est exclue, la dernière valeur est 8.\n"
            },
            {
              "text": "9",
              "correct": false,
              "feedback": "Erreur : la boucle ne part pas de 0 mais de 5, et s'arrête avant\n9.\n"
            },
            {
              "text": "3",
              "correct": false,
              "feedback": "Erreur : de 5 à 8 inclus, il y a 4 valeurs.\n"
            }
          ],
          "explanation": "`range(a, b)` fournit les entiers de `a` inclus à `b` exclu, soit\n`b - a` valeurs. Le nombre de tours ne dépend pas de ce que fait le\ncorps de la boucle."
        }
      ]
    },
    {
      "id": "q03",
      "difficulty": 1,
      "skills": [
        "for",
        "range"
      ],
      "title": "Un range qui descend",
      "statement": "```python\nfor n in range(10, 0, -3):\n    print(n)\n```\n\nQuelles valeurs sont affichées ?",
      "options": [
        {
          "text": "10, 7, 4 et 1",
          "correct": true,
          "feedback": "Bonne réponse : on part de 10 et on retire 3 à chaque fois tant\nqu'on reste strictement au-dessus de 0.\n"
        },
        {
          "text": "10, 7 et 4",
          "correct": false,
          "feedback": "Erreur : 1 est encore strictement supérieur à 0, il est\naffiché.\n"
        },
        {
          "text": "10, 7, 4, 1 et -2",
          "correct": false,
          "feedback": "Erreur : -2 dépasse la borne 0, la boucle s'arrête avant.\n"
        },
        {
          "text": "0, 3, 6 et 9",
          "correct": false,
          "feedback": "Erreur : le premier argument est le point de départ, 10, et le\npas est négatif.\n"
        }
      ],
      "explanation": "`range(depart, fin, pas)` accepte un pas négatif pour compter à\nrebours. La borne `fin` reste exclue, comme toujours."
    },
    {
      "id": "q04",
      "difficulty": 2,
      "skills": [
        "accumulateur",
        "range"
      ],
      "title": "La somme des premiers entiers",
      "statement": "```python\ntotal = 0\nfor i in range(1, 6):\n    total = total + i\nprint(total)\n```\n\nQu'affiche ce programme ?",
      "options": [
        {
          "text": "`15`",
          "correct": true,
          "feedback": "Bonne réponse : la boucle ajoute 1, 2, 3, 4 et 5, ce qui fait\n15.\n"
        },
        {
          "text": "`10`",
          "correct": false,
          "feedback": "Erreur : 10 serait la somme de 1 à 4. La valeur 5 est incluse,\nseule la borne 6 est exclue.\n"
        },
        {
          "text": "`21`",
          "correct": false,
          "feedback": "Erreur : 21 ajouterait 6, qui est exclu par `range(1, 6)`.\n"
        },
        {
          "text": "`5`",
          "correct": false,
          "feedback": "Erreur : `total` accumule les valeurs successives, il ne garde\npas la dernière.\n"
        }
      ],
      "explanation": "L'accumulateur est le schéma de base : une variable initialisée à 0\navant la boucle, à laquelle on ajoute une valeur à chaque tour. À la\nsortie, elle contient la somme.",
      "variants": [
        {
          "statement": "```python\ntotal = 0\nfor i in range(1, 6):\n    total = total + i\nprint(total)\n```\n\nQu'affiche ce programme ?",
          "options": [
            {
              "text": "`15`",
              "correct": true,
              "feedback": "Bonne réponse : la boucle ajoute 1, 2, 3, 4 et 5, ce qui fait\n15.\n"
            },
            {
              "text": "`10`",
              "correct": false,
              "feedback": "Erreur : 10 serait la somme de 1 à 4. La valeur 5 est incluse,\nseule la borne 6 est exclue.\n"
            },
            {
              "text": "`21`",
              "correct": false,
              "feedback": "Erreur : 21 ajouterait 6, qui est exclu par `range(1, 6)`.\n"
            },
            {
              "text": "`5`",
              "correct": false,
              "feedback": "Erreur : `total` accumule les valeurs successives, il ne garde\npas la dernière.\n"
            }
          ],
          "explanation": "L'accumulateur est le schéma de base : une variable initialisée à 0\navant la boucle, à laquelle on ajoute une valeur à chaque tour. À la\nsortie, elle contient la somme."
        },
        {
          "statement": "```python\ntotal = 0\nfor i in range(1, 8):\n    total = total + i\nprint(total)\n```\n\nQu'affiche ce programme ?",
          "options": [
            {
              "text": "`28`",
              "correct": true,
              "feedback": "Bonne réponse : la boucle ajoute 1, 2, 3, 4, 5, 6 et 7, ce qui fait\n28.\n"
            },
            {
              "text": "`21`",
              "correct": false,
              "feedback": "Erreur : 21 serait la somme de 1 à 6. La valeur 7 est incluse,\nseule la borne 8 est exclue.\n"
            },
            {
              "text": "`36`",
              "correct": false,
              "feedback": "Erreur : 36 ajouterait 8, qui est exclu par `range(1, 8)`.\n"
            },
            {
              "text": "`7`",
              "correct": false,
              "feedback": "Erreur : `total` accumule les valeurs successives, il ne garde\npas la dernière.\n"
            }
          ],
          "explanation": "L'accumulateur est le schéma de base : une variable initialisée à 0\navant la boucle, à laquelle on ajoute une valeur à chaque tour. À la\nsortie, elle contient la somme."
        },
        {
          "statement": "```python\ntotal = 0\nfor i in range(1, 11):\n    total = total + i\nprint(total)\n```\n\nQu'affiche ce programme ?",
          "options": [
            {
              "text": "`55`",
              "correct": true,
              "feedback": "Bonne réponse : la boucle ajoute 1, 2, 3, 4, 5, 6, 7, 8, 9 et 10, ce qui fait\n55.\n"
            },
            {
              "text": "`45`",
              "correct": false,
              "feedback": "Erreur : 45 serait la somme de 1 à 9. La valeur 10 est incluse,\nseule la borne 11 est exclue.\n"
            },
            {
              "text": "`66`",
              "correct": false,
              "feedback": "Erreur : 66 ajouterait 11, qui est exclu par `range(1, 11)`.\n"
            },
            {
              "text": "`10`",
              "correct": false,
              "feedback": "Erreur : `total` accumule les valeurs successives, il ne garde\npas la dernière.\n"
            }
          ],
          "explanation": "L'accumulateur est le schéma de base : une variable initialisée à 0\navant la boucle, à laquelle on ajoute une valeur à chaque tour. À la\nsortie, elle contient la somme."
        }
      ]
    },
    {
      "id": "q05",
      "difficulty": 2,
      "skills": [
        "compteur",
        "condition",
        "modulo"
      ],
      "title": "Compter les multiples",
      "statement": "```python\ncompte = 0\nfor n in range(1, 21):\n    if n % 5 == 0:\n        compte = compte + 1\nprint(compte)\n```\n\nQu'affiche ce programme ?",
      "options": [
        {
          "text": "`4`",
          "correct": true,
          "feedback": "Bonne réponse : entre 1 et 20, les multiples de 5 sont 5, 10, 15 et 20.\n"
        },
        {
          "text": "`5`",
          "correct": false,
          "feedback": "Erreur : 25 n'est pas atteint, la boucle s'arrête à 20.\n"
        },
        {
          "text": "`20`",
          "correct": false,
          "feedback": "Erreur : le compteur n'augmente que quand la condition est\nvraie, pas à chaque tour.\n"
        },
        {
          "text": "`3`",
          "correct": false,
          "feedback": "Erreur : 20 est bien parcouru, `range(1, 21)` va jusqu'à 20.\n"
        }
      ],
      "explanation": "Le compteur est un accumulateur qui n'augmente que sous condition.\nUne variable à 0, un `if` dans la boucle, et un ajout de 1 quand la\npropriété est vérifiée.",
      "variants": [
        {
          "statement": "```python\ncompte = 0\nfor n in range(1, 21):\n    if n % 5 == 0:\n        compte = compte + 1\nprint(compte)\n```\n\nQu'affiche ce programme ?",
          "options": [
            {
              "text": "`4`",
              "correct": true,
              "feedback": "Bonne réponse : entre 1 et 20, les multiples de 5 sont 5, 10, 15 et 20.\n"
            },
            {
              "text": "`5`",
              "correct": false,
              "feedback": "Erreur : 25 n'est pas atteint, la boucle s'arrête à 20.\n"
            },
            {
              "text": "`20`",
              "correct": false,
              "feedback": "Erreur : le compteur n'augmente que quand la condition est\nvraie, pas à chaque tour.\n"
            },
            {
              "text": "`3`",
              "correct": false,
              "feedback": "Erreur : 20 est bien parcouru, `range(1, 21)` va jusqu'à 20.\n"
            }
          ],
          "explanation": "Le compteur est un accumulateur qui n'augmente que sous condition.\nUne variable à 0, un `if` dans la boucle, et un ajout de 1 quand la\npropriété est vérifiée."
        },
        {
          "statement": "```python\ncompte = 0\nfor n in range(1, 19):\n    if n % 3 == 0:\n        compte = compte + 1\nprint(compte)\n```\n\nQu'affiche ce programme ?",
          "options": [
            {
              "text": "`6`",
              "correct": true,
              "feedback": "Bonne réponse : entre 1 et 18, les multiples de 3 sont 3, 6, 9, 12, 15 et 18.\n"
            },
            {
              "text": "`7`",
              "correct": false,
              "feedback": "Erreur : 21 n'est pas atteint, la boucle s'arrête à 18.\n"
            },
            {
              "text": "`18`",
              "correct": false,
              "feedback": "Erreur : le compteur n'augmente que quand la condition est\nvraie, pas à chaque tour.\n"
            },
            {
              "text": "`5`",
              "correct": false,
              "feedback": "Erreur : 18 est bien parcouru, `range(1, 19)` va jusqu'à 18.\n"
            }
          ],
          "explanation": "Le compteur est un accumulateur qui n'augmente que sous condition.\nUne variable à 0, un `if` dans la boucle, et un ajout de 1 quand la\npropriété est vérifiée."
        },
        {
          "statement": "```python\ncompte = 0\nfor n in range(1, 29):\n    if n % 4 == 0:\n        compte = compte + 1\nprint(compte)\n```\n\nQu'affiche ce programme ?",
          "options": [
            {
              "text": "`7`",
              "correct": true,
              "feedback": "Bonne réponse : entre 1 et 28, les multiples de 4 sont 4, 8, 12, 16, 20, 24 et 28.\n"
            },
            {
              "text": "`8`",
              "correct": false,
              "feedback": "Erreur : 32 n'est pas atteint, la boucle s'arrête à 28.\n"
            },
            {
              "text": "`28`",
              "correct": false,
              "feedback": "Erreur : le compteur n'augmente que quand la condition est\nvraie, pas à chaque tour.\n"
            },
            {
              "text": "`6`",
              "correct": false,
              "feedback": "Erreur : 28 est bien parcouru, `range(1, 29)` va jusqu'à 28.\n"
            }
          ],
          "explanation": "Le compteur est un accumulateur qui n'augmente que sous condition.\nUne variable à 0, un `if` dans la boucle, et un ajout de 1 quand la\npropriété est vérifiée."
        }
      ]
    },
    {
      "id": "q06",
      "difficulty": 2,
      "skills": [
        "variable",
        "portee",
        "trace"
      ],
      "title": "La valeur qui reste",
      "statement": "```python\nfor i in range(3):\n    x = i * 10\nprint(x)\n```\n\nQu'affiche ce programme ?",
      "options": [
        {
          "text": "`20`",
          "correct": true,
          "feedback": "Bonne réponse : `x` est recalculé à chaque tour ; au dernier,\n`i` vaut 2 et `x` vaut 20. Cette valeur subsiste après la\nboucle.\n"
        },
        {
          "text": "`30`",
          "correct": false,
          "feedback": "Erreur : `i` prend les valeurs 0, 1 et 2, jamais 3.\n"
        },
        {
          "text": "`0`",
          "correct": false,
          "feedback": "Erreur : 0 est la valeur au premier tour, écrasée ensuite.\n"
        },
        {
          "text": "Une erreur, `x` n'existe plus après la boucle",
          "correct": false,
          "feedback": "Erreur : une variable créée dans une boucle reste accessible\naprès. Elle garde sa dernière valeur.\n"
        }
      ],
      "explanation": "Les variables modifiées dans la boucle conservent leur dernière\nvaleur à la sortie. Il en va de même pour la variable de boucle\nelle-même.",
      "variants": [
        {
          "statement": "```python\nfor i in range(3):\n    x = i * 10\nprint(x)\n```\n\nQu'affiche ce programme ?",
          "options": [
            {
              "text": "`20`",
              "correct": true,
              "feedback": "Bonne réponse : `x` est recalculé à chaque tour ; au dernier,\n`i` vaut 2 et `x` vaut 20. Cette valeur subsiste après la\nboucle.\n"
            },
            {
              "text": "`30`",
              "correct": false,
              "feedback": "Erreur : `i` prend les valeurs 0, 1 et 2, jamais 3.\n"
            },
            {
              "text": "`0`",
              "correct": false,
              "feedback": "Erreur : 0 est la valeur au premier tour, écrasée ensuite.\n"
            },
            {
              "text": "Une erreur, `x` n'existe plus après la boucle",
              "correct": false,
              "feedback": "Erreur : une variable créée dans une boucle reste accessible\naprès. Elle garde sa dernière valeur.\n"
            }
          ],
          "explanation": "Les variables modifiées dans la boucle conservent leur dernière\nvaleur à la sortie. Il en va de même pour la variable de boucle\nelle-même."
        },
        {
          "statement": "```python\nfor i in range(4):\n    x = i * 5\nprint(x)\n```\n\nQu'affiche ce programme ?",
          "options": [
            {
              "text": "`15`",
              "correct": true,
              "feedback": "Bonne réponse : `x` est recalculé à chaque tour ; au dernier,\n`i` vaut 3 et `x` vaut 15. Cette valeur subsiste après la\nboucle.\n"
            },
            {
              "text": "`20`",
              "correct": false,
              "feedback": "Erreur : `i` prend les valeurs 0, 1, 2 et 3, jamais 4.\n"
            },
            {
              "text": "`0`",
              "correct": false,
              "feedback": "Erreur : 0 est la valeur au premier tour, écrasée ensuite.\n"
            },
            {
              "text": "Une erreur, `x` n'existe plus après la boucle",
              "correct": false,
              "feedback": "Erreur : une variable créée dans une boucle reste accessible\naprès. Elle garde sa dernière valeur.\n"
            }
          ],
          "explanation": "Les variables modifiées dans la boucle conservent leur dernière\nvaleur à la sortie. Il en va de même pour la variable de boucle\nelle-même."
        },
        {
          "statement": "```python\nfor i in range(6):\n    x = i * 7\nprint(x)\n```\n\nQu'affiche ce programme ?",
          "options": [
            {
              "text": "`35`",
              "correct": true,
              "feedback": "Bonne réponse : `x` est recalculé à chaque tour ; au dernier,\n`i` vaut 5 et `x` vaut 35. Cette valeur subsiste après la\nboucle.\n"
            },
            {
              "text": "`42`",
              "correct": false,
              "feedback": "Erreur : `i` prend les valeurs 0, 1, 2, 3, 4 et 5, jamais 6.\n"
            },
            {
              "text": "`0`",
              "correct": false,
              "feedback": "Erreur : 0 est la valeur au premier tour, écrasée ensuite.\n"
            },
            {
              "text": "Une erreur, `x` n'existe plus après la boucle",
              "correct": false,
              "feedback": "Erreur : une variable créée dans une boucle reste accessible\naprès. Elle garde sa dernière valeur.\n"
            }
          ],
          "explanation": "Les variables modifiées dans la boucle conservent leur dernière\nvaleur à la sortie. Il en va de même pour la variable de boucle\nelle-même."
        }
      ]
    },
    {
      "id": "q07",
      "difficulty": 2,
      "skills": [
        "for",
        "parcours-chaine"
      ],
      "title": "Parcourir une chaîne",
      "statement": "```python\nfor lettre in \"SNT\":\n    print(lettre)\n```\n\nQu'affiche ce programme ?",
      "options": [
        {
          "text": "`S`, `N` et `T`, sur trois lignes",
          "correct": true,
          "feedback": "Bonne réponse : la boucle parcourt la chaîne caractère par\ncaractère, et chaque `print` occupe une ligne.\n"
        },
        {
          "text": "`SNT` sur une seule ligne, sans retour",
          "correct": false,
          "feedback": "Erreur : chaque tour affiche un seul caractère et revient à la\nligne.\n"
        },
        {
          "text": "0, 1 et 2, les positions des lettres",
          "correct": false,
          "feedback": "Erreur : en parcourant une chaîne, la variable reçoit les\ncaractères, pas leurs positions.\n"
        },
        {
          "text": "`lettre` trois fois, sur trois lignes",
          "correct": false,
          "feedback": "Erreur : `print(lettre)` affiche la valeur de la variable, un\ncaractère différent à chaque tour.\n"
        }
      ],
      "explanation": "`for` sait parcourir une chaîne : la variable prend successivement\nchaque caractère. Pas besoin de `range` pour cela."
    },
    {
      "id": "q08",
      "difficulty": 2,
      "skills": [
        "chaine",
        "compteur",
        "parcours"
      ],
      "title": "Compter une lettre",
      "statement": "```python\ncompte = 0\nfor c in \"programmation\":\n    if c == \"a\":\n        compte = compte + 1\nprint(compte)\n```\n\nQu'affiche ce programme ?",
      "options": [
        {
          "text": "`2`",
          "correct": true,
          "feedback": "Bonne réponse : en épelant « programmation », on trouve 2 fois la\nlettre `a`.\n"
        },
        {
          "text": "`3`",
          "correct": false,
          "feedback": "Erreur : en épelant le mot, on ne trouve que 2 fois la lettre `a`.\n"
        },
        {
          "text": "`1`",
          "correct": false,
          "feedback": "Erreur : chaque `a` rencontré ajoute 1, et il y en a 2.\n"
        },
        {
          "text": "`13`",
          "correct": false,
          "feedback": "Erreur : 13 est le nombre de tours, mais le compteur n'augmente\nque sur les `a`.\n"
        }
      ],
      "explanation": "Compter une lettre combine le parcours d'une chaîne et le schéma du\ncompteur : un test sur chaque caractère, un ajout de 1 quand il\nconvient.",
      "variants": [
        {
          "statement": "```python\ncompte = 0\nfor c in \"programmation\":\n    if c == \"a\":\n        compte = compte + 1\nprint(compte)\n```\n\nQu'affiche ce programme ?",
          "options": [
            {
              "text": "`2`",
              "correct": true,
              "feedback": "Bonne réponse : en épelant « programmation », on trouve 2 fois la\nlettre `a`.\n"
            },
            {
              "text": "`3`",
              "correct": false,
              "feedback": "Erreur : en épelant le mot, on ne trouve que 2 fois la lettre `a`.\n"
            },
            {
              "text": "`1`",
              "correct": false,
              "feedback": "Erreur : chaque `a` rencontré ajoute 1, et il y en a 2.\n"
            },
            {
              "text": "`13`",
              "correct": false,
              "feedback": "Erreur : 13 est le nombre de tours, mais le compteur n'augmente\nque sur les `a`.\n"
            }
          ],
          "explanation": "Compter une lettre combine le parcours d'une chaîne et le schéma du\ncompteur : un test sur chaque caractère, un ajout de 1 quand il\nconvient."
        },
        {
          "statement": "```python\ncompte = 0\nfor c in \"statistique\":\n    if c == \"t\":\n        compte = compte + 1\nprint(compte)\n```\n\nQu'affiche ce programme ?",
          "options": [
            {
              "text": "`3`",
              "correct": true,
              "feedback": "Bonne réponse : en épelant « statistique », on trouve 3 fois la\nlettre `t`.\n"
            },
            {
              "text": "`4`",
              "correct": false,
              "feedback": "Erreur : en épelant le mot, on ne trouve que 3 fois la lettre `t`.\n"
            },
            {
              "text": "`2`",
              "correct": false,
              "feedback": "Erreur : chaque `t` rencontré ajoute 1, et il y en a 3.\n"
            },
            {
              "text": "`11`",
              "correct": false,
              "feedback": "Erreur : 11 est le nombre de tours, mais le compteur n'augmente\nque sur les `t`.\n"
            }
          ],
          "explanation": "Compter une lettre combine le parcours d'une chaîne et le schéma du\ncompteur : un test sur chaque caractère, un ajout de 1 quand il\nconvient."
        },
        {
          "statement": "```python\ncompte = 0\nfor c in \"navigateur\":\n    if c == \"n\":\n        compte = compte + 1\nprint(compte)\n```\n\nQu'affiche ce programme ?",
          "options": [
            {
              "text": "`1`",
              "correct": true,
              "feedback": "Bonne réponse : en épelant « navigateur », on trouve 1 fois la\nlettre `n`.\n"
            },
            {
              "text": "`2`",
              "correct": false,
              "feedback": "Erreur : en épelant le mot, on ne trouve que 1 fois la lettre `n`.\n"
            },
            {
              "text": "`0`",
              "correct": false,
              "feedback": "Erreur : chaque `n` rencontré ajoute 1, et il y en a 1.\n"
            },
            {
              "text": "`10`",
              "correct": false,
              "feedback": "Erreur : 10 est le nombre de tours, mais le compteur n'augmente\nque sur les `n`.\n"
            }
          ],
          "explanation": "Compter une lettre combine le parcours d'une chaîne et le schéma du\ncompteur : un test sur chaque caractère, un ajout de 1 quand il\nconvient."
        }
      ]
    },
    {
      "id": "q09",
      "difficulty": 3,
      "skills": [
        "for",
        "trace",
        "accumulateur"
      ],
      "title": "Afficher avant d'ajouter",
      "statement": "```python\ns = 0\nfor k in range(3):\n    print(s)\n    s = s + k\n```\n\nQu'affiche ce programme ?",
      "options": [
        {
          "text": "0, 0 et 1",
          "correct": true,
          "feedback": "Bonne réponse : au premier tour `s` vaut 0 ; puis on ajoute 0.\nAu deuxième, `s` vaut encore 0 ; puis on ajoute 1. Au troisième,\n`s` vaut 1.\n"
        },
        {
          "text": "0, 1 et 3",
          "correct": false,
          "feedback": "Erreur : ce seraient les valeurs après chaque ajout. Or le\n`print` vient avant l'ajout.\n"
        },
        {
          "text": "0, 1 et 2",
          "correct": false,
          "feedback": "Erreur : le programme affiche `s`, pas `k`.\n"
        },
        {
          "text": "1, 3 et 6",
          "correct": false,
          "feedback": "Erreur : `k` part de 0, et l'affichage précède l'ajout.\n"
        }
      ],
      "explanation": "La place du `print` dans le corps de la boucle change ce qui est\naffiché. Une trace tour par tour, avec les valeurs de `k` et de `s`,\nlève tout doute."
    },
    {
      "id": "q10",
      "difficulty": 3,
      "skills": [
        "boucles-imbriquees",
        "tours"
      ],
      "title": "Deux boucles imbriquées",
      "statement": "```python\nfor i in range(2):\n    for j in range(3):\n        print(i, j)\n```\n\nCombien de lignes ce programme affiche-t-il ?",
      "options": [
        {
          "text": "6",
          "correct": true,
          "feedback": "Bonne réponse : pour chacune des 2 valeurs de `i`, la boucle\nintérieure fait 3 tours, soit 2 fois 3 lignes.\n"
        },
        {
          "text": "5",
          "correct": false,
          "feedback": "Erreur : les tours se multiplient, ils ne s'additionnent pas.\n"
        },
        {
          "text": "3",
          "correct": false,
          "feedback": "Erreur : la boucle intérieure est relancée entièrement pour\nchaque valeur de `i`.\n"
        },
        {
          "text": "2",
          "correct": false,
          "feedback": "Erreur : chaque tour de la boucle extérieure déclenche 3\naffichages.\n"
        }
      ],
      "explanation": "Quand une boucle en contient une autre, le nombre total de passages\nest le produit des nombres de tours. Ici, `(0, 0)`, `(0, 1)`, et\nainsi de suite jusqu'à `(0, 2)`, puis la même chose pour chaque\nvaleur suivante de `i`.",
      "variants": [
        {
          "statement": "```python\nfor i in range(2):\n    for j in range(3):\n        print(i, j)\n```\n\nCombien de lignes ce programme affiche-t-il ?",
          "options": [
            {
              "text": "6",
              "correct": true,
              "feedback": "Bonne réponse : pour chacune des 2 valeurs de `i`, la boucle\nintérieure fait 3 tours, soit 2 fois 3 lignes.\n"
            },
            {
              "text": "5",
              "correct": false,
              "feedback": "Erreur : les tours se multiplient, ils ne s'additionnent pas.\n"
            },
            {
              "text": "3",
              "correct": false,
              "feedback": "Erreur : la boucle intérieure est relancée entièrement pour\nchaque valeur de `i`.\n"
            },
            {
              "text": "2",
              "correct": false,
              "feedback": "Erreur : chaque tour de la boucle extérieure déclenche 3\naffichages.\n"
            }
          ],
          "explanation": "Quand une boucle en contient une autre, le nombre total de passages\nest le produit des nombres de tours. Ici, `(0, 0)`, `(0, 1)`, et\nainsi de suite jusqu'à `(0, 2)`, puis la même chose pour chaque\nvaleur suivante de `i`."
        },
        {
          "statement": "```python\nfor i in range(3):\n    for j in range(4):\n        print(i, j)\n```\n\nCombien de lignes ce programme affiche-t-il ?",
          "options": [
            {
              "text": "12",
              "correct": true,
              "feedback": "Bonne réponse : pour chacune des 3 valeurs de `i`, la boucle\nintérieure fait 4 tours, soit 3 fois 4 lignes.\n"
            },
            {
              "text": "7",
              "correct": false,
              "feedback": "Erreur : les tours se multiplient, ils ne s'additionnent pas.\n"
            },
            {
              "text": "4",
              "correct": false,
              "feedback": "Erreur : la boucle intérieure est relancée entièrement pour\nchaque valeur de `i`.\n"
            },
            {
              "text": "3",
              "correct": false,
              "feedback": "Erreur : chaque tour de la boucle extérieure déclenche 4\naffichages.\n"
            }
          ],
          "explanation": "Quand une boucle en contient une autre, le nombre total de passages\nest le produit des nombres de tours. Ici, `(0, 0)`, `(0, 1)`, et\nainsi de suite jusqu'à `(0, 3)`, puis la même chose pour chaque\nvaleur suivante de `i`."
        },
        {
          "statement": "```python\nfor i in range(2):\n    for j in range(5):\n        print(i, j)\n```\n\nCombien de lignes ce programme affiche-t-il ?",
          "options": [
            {
              "text": "10",
              "correct": true,
              "feedback": "Bonne réponse : pour chacune des 2 valeurs de `i`, la boucle\nintérieure fait 5 tours, soit 2 fois 5 lignes.\n"
            },
            {
              "text": "7",
              "correct": false,
              "feedback": "Erreur : les tours se multiplient, ils ne s'additionnent pas.\n"
            },
            {
              "text": "5",
              "correct": false,
              "feedback": "Erreur : la boucle intérieure est relancée entièrement pour\nchaque valeur de `i`.\n"
            },
            {
              "text": "2",
              "correct": false,
              "feedback": "Erreur : chaque tour de la boucle extérieure déclenche 5\naffichages.\n"
            }
          ],
          "explanation": "Quand une boucle en contient une autre, le nombre total de passages\nest le produit des nombres de tours. Ici, `(0, 0)`, `(0, 1)`, et\nainsi de suite jusqu'à `(0, 4)`, puis la même chose pour chaque\nvaleur suivante de `i`."
        }
      ]
    },
    {
      "id": "q11",
      "difficulty": 2,
      "skills": [
        "range",
        "pas"
      ],
      "title": "La dernière valeur affichée",
      "statement": "```python\nfor i in range(1, 10, 2):\n    print(i)\n```\n\nQuelle est la dernière valeur affichée ?",
      "options": [
        {
          "text": "`9`",
          "correct": true,
          "feedback": "Bonne réponse : les valeurs sont 1, 3, 5, 7 et 9. La suivante,\n11, dépasse la borne.\n"
        },
        {
          "text": "`10`",
          "correct": false,
          "feedback": "Erreur : la borne 10 est exclue, et de toute façon le pas de 2\nne l'atteint pas.\n"
        },
        {
          "text": "`7`",
          "correct": false,
          "feedback": "Erreur : 9 est encore strictement inférieur à 10, il est\naffiché.\n"
        },
        {
          "text": "`8`",
          "correct": false,
          "feedback": "Erreur : en partant de 1 avec un pas de 2, on ne passe que par\n1, 3, 5 et ainsi de suite.\n"
        }
      ],
      "explanation": "Avec trois arguments, `range` part du premier, avance du troisième\net s'arrête avant le deuxième. Ici, il énumère 1, 3, 5, 7 et 9.",
      "variants": [
        {
          "statement": "```python\nfor i in range(1, 10, 2):\n    print(i)\n```\n\nQuelle est la dernière valeur affichée ?",
          "options": [
            {
              "text": "`9`",
              "correct": true,
              "feedback": "Bonne réponse : les valeurs sont 1, 3, 5, 7 et 9. La suivante,\n11, dépasse la borne.\n"
            },
            {
              "text": "`10`",
              "correct": false,
              "feedback": "Erreur : la borne 10 est exclue, et de toute façon le pas de 2\nne l'atteint pas.\n"
            },
            {
              "text": "`7`",
              "correct": false,
              "feedback": "Erreur : 9 est encore strictement inférieur à 10, il est\naffiché.\n"
            },
            {
              "text": "`8`",
              "correct": false,
              "feedback": "Erreur : en partant de 1 avec un pas de 2, on ne passe que par\n1, 3, 5 et ainsi de suite.\n"
            }
          ],
          "explanation": "Avec trois arguments, `range` part du premier, avance du troisième\net s'arrête avant le deuxième. Ici, il énumère 1, 3, 5, 7 et 9."
        },
        {
          "statement": "```python\nfor i in range(2, 15, 3):\n    print(i)\n```\n\nQuelle est la dernière valeur affichée ?",
          "options": [
            {
              "text": "`14`",
              "correct": true,
              "feedback": "Bonne réponse : les valeurs sont 2, 5, 8, 11 et 14. La suivante,\n17, dépasse la borne.\n"
            },
            {
              "text": "`15`",
              "correct": false,
              "feedback": "Erreur : la borne 15 est exclue, et de toute façon le pas de 3\nne l'atteint pas.\n"
            },
            {
              "text": "`11`",
              "correct": false,
              "feedback": "Erreur : 14 est encore strictement inférieur à 15, il est\naffiché.\n"
            },
            {
              "text": "`13`",
              "correct": false,
              "feedback": "Erreur : en partant de 2 avec un pas de 3, on ne passe que par\n2, 5, 8 et ainsi de suite.\n"
            }
          ],
          "explanation": "Avec trois arguments, `range` part du premier, avance du troisième\net s'arrête avant le deuxième. Ici, il énumère 2, 5, 8, 11 et 14."
        },
        {
          "statement": "```python\nfor i in range(5, 30, 4):\n    print(i)\n```\n\nQuelle est la dernière valeur affichée ?",
          "options": [
            {
              "text": "`29`",
              "correct": true,
              "feedback": "Bonne réponse : les valeurs sont 5, 9, 13, 17, 21, 25 et 29. La suivante,\n33, dépasse la borne.\n"
            },
            {
              "text": "`30`",
              "correct": false,
              "feedback": "Erreur : la borne 30 est exclue, et de toute façon le pas de 4\nne l'atteint pas.\n"
            },
            {
              "text": "`25`",
              "correct": false,
              "feedback": "Erreur : 29 est encore strictement inférieur à 30, il est\naffiché.\n"
            },
            {
              "text": "`28`",
              "correct": false,
              "feedback": "Erreur : en partant de 5 avec un pas de 4, on ne passe que par\n5, 9, 13 et ainsi de suite.\n"
            }
          ],
          "explanation": "Avec trois arguments, `range` part du premier, avance du troisième\net s'arrête avant le deuxième. Ici, il énumère 5, 9, 13, 17, 21, 25 et 29."
        }
      ]
    },
    {
      "id": "q12",
      "difficulty": 2,
      "skills": [
        "accumulateur",
        "produit"
      ],
      "title": "Un produit",
      "statement": "```python\np = 1\nfor i in range(1, 5):\n    p = p * i\nprint(p)\n```\n\nQu'affiche ce programme ?",
      "options": [
        {
          "text": "`24`",
          "correct": true,
          "feedback": "Bonne réponse : 1 fois 2 fois 3 fois 4 font 24.\n"
        },
        {
          "text": "`120`",
          "correct": false,
          "feedback": "Erreur : 120 inclurait le facteur 5, exclu par `range(1, 5)`.\n"
        },
        {
          "text": "`10`",
          "correct": false,
          "feedback": "Erreur : 10 serait la somme de 1 à 4, or la boucle multiplie.\n"
        },
        {
          "text": "`0`",
          "correct": false,
          "feedback": "Erreur : `p` part de 1, pas de 0. Un produit initialisé à 0\nresterait nul.\n"
        }
      ],
      "explanation": "Pour accumuler un produit, on initialise à 1, pas à 0. Le schéma est\ncelui de l'accumulateur, avec une multiplication à la place de\nl'addition.",
      "variants": [
        {
          "statement": "```python\np = 1\nfor i in range(1, 5):\n    p = p * i\nprint(p)\n```\n\nQu'affiche ce programme ?",
          "options": [
            {
              "text": "`24`",
              "correct": true,
              "feedback": "Bonne réponse : 1 fois 2 fois 3 fois 4 font 24.\n"
            },
            {
              "text": "`120`",
              "correct": false,
              "feedback": "Erreur : 120 inclurait le facteur 5, exclu par `range(1, 5)`.\n"
            },
            {
              "text": "`10`",
              "correct": false,
              "feedback": "Erreur : 10 serait la somme de 1 à 4, or la boucle multiplie.\n"
            },
            {
              "text": "`0`",
              "correct": false,
              "feedback": "Erreur : `p` part de 1, pas de 0. Un produit initialisé à 0\nresterait nul.\n"
            }
          ],
          "explanation": "Pour accumuler un produit, on initialise à 1, pas à 0. Le schéma est\ncelui de l'accumulateur, avec une multiplication à la place de\nl'addition."
        },
        {
          "statement": "```python\np = 1\nfor i in range(1, 6):\n    p = p * i\nprint(p)\n```\n\nQu'affiche ce programme ?",
          "options": [
            {
              "text": "`120`",
              "correct": true,
              "feedback": "Bonne réponse : 1 fois 2 fois 3 fois 4 fois 5 font 120.\n"
            },
            {
              "text": "`720`",
              "correct": false,
              "feedback": "Erreur : 720 inclurait le facteur 6, exclu par `range(1, 6)`.\n"
            },
            {
              "text": "`15`",
              "correct": false,
              "feedback": "Erreur : 15 serait la somme de 1 à 5, or la boucle multiplie.\n"
            },
            {
              "text": "`0`",
              "correct": false,
              "feedback": "Erreur : `p` part de 1, pas de 0. Un produit initialisé à 0\nresterait nul.\n"
            }
          ],
          "explanation": "Pour accumuler un produit, on initialise à 1, pas à 0. Le schéma est\ncelui de l'accumulateur, avec une multiplication à la place de\nl'addition."
        },
        {
          "statement": "```python\np = 1\nfor i in range(1, 7):\n    p = p * i\nprint(p)\n```\n\nQu'affiche ce programme ?",
          "options": [
            {
              "text": "`720`",
              "correct": true,
              "feedback": "Bonne réponse : 1 fois 2 fois 3 fois 4 fois 5 fois 6 font 720.\n"
            },
            {
              "text": "`5040`",
              "correct": false,
              "feedback": "Erreur : 5040 inclurait le facteur 7, exclu par `range(1, 7)`.\n"
            },
            {
              "text": "`21`",
              "correct": false,
              "feedback": "Erreur : 21 serait la somme de 1 à 6, or la boucle multiplie.\n"
            },
            {
              "text": "`0`",
              "correct": false,
              "feedback": "Erreur : `p` part de 1, pas de 0. Un produit initialisé à 0\nresterait nul.\n"
            }
          ],
          "explanation": "Pour accumuler un produit, on initialise à 1, pas à 0. Le schéma est\ncelui de l'accumulateur, avec une multiplication à la place de\nl'addition."
        }
      ]
    },
    {
      "id": "q13",
      "difficulty": 3,
      "skills": [
        "variable-de-boucle",
        "trace"
      ],
      "title": "Modifier la variable de boucle",
      "statement": "```python\nfor i in range(3):\n    i = i + 10\n    print(i)\n```\n\nQu'affiche ce programme ?",
      "options": [
        {
          "text": "10, 11 et 12",
          "correct": true,
          "feedback": "Bonne réponse : à chaque tour, `i` reçoit la valeur suivante de\n`range`, 0, 1 et 2, avant l'ajout de 10.\n"
        },
        {
          "text": "10, 21 et 32",
          "correct": false,
          "feedback": "Erreur : la modification de `i` ne se cumule pas. `range`\nréaffecte `i` au début de chaque tour.\n"
        },
        {
          "text": "10, puis une erreur",
          "correct": false,
          "feedback": "Erreur : modifier la variable de boucle est autorisé, même si\nc'est déconseillé.\n"
        },
        {
          "text": "0, 1 et 2",
          "correct": false,
          "feedback": "Erreur : l'ajout de 10 a lieu avant l'affichage.\n"
        }
      ],
      "explanation": "Au début de chaque tour, `for` donne à sa variable la valeur suivante\nde `range`, quoi qu'on lui ait fait au tour précédent. Modifier la\nvariable de boucle n'influence pas le nombre de tours.",
      "variants": [
        {
          "statement": "```python\nfor i in range(3):\n    i = i + 10\n    print(i)\n```\n\nQu'affiche ce programme ?",
          "options": [
            {
              "text": "10, 11 et 12",
              "correct": true,
              "feedback": "Bonne réponse : à chaque tour, `i` reçoit la valeur suivante de\n`range`, 0, 1 et 2, avant l'ajout de 10.\n"
            },
            {
              "text": "10, 21 et 32",
              "correct": false,
              "feedback": "Erreur : la modification de `i` ne se cumule pas. `range`\nréaffecte `i` au début de chaque tour.\n"
            },
            {
              "text": "10, puis une erreur",
              "correct": false,
              "feedback": "Erreur : modifier la variable de boucle est autorisé, même si\nc'est déconseillé.\n"
            },
            {
              "text": "0, 1 et 2",
              "correct": false,
              "feedback": "Erreur : l'ajout de 10 a lieu avant l'affichage.\n"
            }
          ],
          "explanation": "Au début de chaque tour, `for` donne à sa variable la valeur suivante\nde `range`, quoi qu'on lui ait fait au tour précédent. Modifier la\nvariable de boucle n'influence pas le nombre de tours."
        },
        {
          "statement": "```python\nfor i in range(4):\n    i = i + 100\n    print(i)\n```\n\nQu'affiche ce programme ?",
          "options": [
            {
              "text": "100, 101, 102 et 103",
              "correct": true,
              "feedback": "Bonne réponse : à chaque tour, `i` reçoit la valeur suivante de\n`range`, 0, 1, 2 et 3, avant l'ajout de 100.\n"
            },
            {
              "text": "100, 201, 302 et 403",
              "correct": false,
              "feedback": "Erreur : la modification de `i` ne se cumule pas. `range`\nréaffecte `i` au début de chaque tour.\n"
            },
            {
              "text": "100, puis une erreur",
              "correct": false,
              "feedback": "Erreur : modifier la variable de boucle est autorisé, même si\nc'est déconseillé.\n"
            },
            {
              "text": "0, 1, 2 et 3",
              "correct": false,
              "feedback": "Erreur : l'ajout de 100 a lieu avant l'affichage.\n"
            }
          ],
          "explanation": "Au début de chaque tour, `for` donne à sa variable la valeur suivante\nde `range`, quoi qu'on lui ait fait au tour précédent. Modifier la\nvariable de boucle n'influence pas le nombre de tours."
        },
        {
          "statement": "```python\nfor i in range(3):\n    i = i + 7\n    print(i)\n```\n\nQu'affiche ce programme ?",
          "options": [
            {
              "text": "7, 8 et 9",
              "correct": true,
              "feedback": "Bonne réponse : à chaque tour, `i` reçoit la valeur suivante de\n`range`, 0, 1 et 2, avant l'ajout de 7.\n"
            },
            {
              "text": "7, 15 et 23",
              "correct": false,
              "feedback": "Erreur : la modification de `i` ne se cumule pas. `range`\nréaffecte `i` au début de chaque tour.\n"
            },
            {
              "text": "7, puis une erreur",
              "correct": false,
              "feedback": "Erreur : modifier la variable de boucle est autorisé, même si\nc'est déconseillé.\n"
            },
            {
              "text": "0, 1 et 2",
              "correct": false,
              "feedback": "Erreur : l'ajout de 7 a lieu avant l'affichage.\n"
            }
          ],
          "explanation": "Au début de chaque tour, `for` donne à sa variable la valeur suivante\nde `range`, quoi qu'on lui ait fait au tour précédent. Modifier la\nvariable de boucle n'influence pas le nombre de tours."
        }
      ]
    },
    {
      "id": "q14",
      "difficulty": 1,
      "skills": [
        "range"
      ],
      "title": "La borne exclue",
      "statement": "La valeur 5 est-elle affichée par la boucle suivante ?\n\n```python\nfor i in range(5):\n    print(i)\n```",
      "options": [
        {
          "text": "Non, `range(5)` s'arrête à 4",
          "correct": true,
          "feedback": "Bonne réponse : `range(5)` fournit 0, 1, 2, 3 et 4, soit cinq\nvaleurs, mais pas 5.\n"
        },
        {
          "text": "Oui, en dernier",
          "correct": false,
          "feedback": "Erreur : la borne donnée à `range` est toujours exclue.\n"
        },
        {
          "text": "Oui, en premier",
          "correct": false,
          "feedback": "Erreur : la boucle commence à 0.\n"
        },
        {
          "text": "Oui, cinq fois de suite",
          "correct": false,
          "feedback": "Erreur : `i` change à chaque tour et ne vaut jamais 5.\n"
        }
      ],
      "explanation": "`range(n)` compte de 0 à `n - 1`. Retenir que la borne est exclue\névite l'erreur classique du « tour de trop » ou du « tour de moins »."
    },
    {
      "id": "q15",
      "difficulty": 2,
      "skills": [
        "for",
        "completer-code",
        "range"
      ],
      "title": "Compléter une boucle",
      "statement": "On veut afficher tous les entiers de 3 à 12 inclus. Quelle ligne\nconvient ?",
      "options": [
        {
          "text": "`for n in range(3, 13):`",
          "correct": true,
          "feedback": "Bonne réponse : pour inclure 12, la borne exclue doit être 13.\n"
        },
        {
          "text": "`for n in range(3, 12):`",
          "correct": false,
          "feedback": "Erreur : 12 serait exclu, la boucle s'arrêterait à 11.\n"
        },
        {
          "text": "`for n in range(12):`",
          "correct": false,
          "feedback": "Erreur : cette boucle part de 0 et s'arrête à 11.\n"
        },
        {
          "text": "`for n in range(13, 3):`",
          "correct": false,
          "feedback": "Erreur : avec un départ supérieur à la borne et un pas positif,\n`range` est vide : aucun tour.\n"
        }
      ],
      "explanation": "Pour parcourir de `a` à `b` inclus, on écrit `range(a, b + 1)`. Le\n« plus un » compense l'exclusion de la borne."
    },
    {
      "id": "q16",
      "difficulty": 3,
      "skills": [
        "accumulateur",
        "condition",
        "modulo"
      ],
      "title": "La somme des nombres pairs",
      "statement": "```python\ns = 0\nfor n in range(1, 11):\n    if n % 2 == 0:\n        s = s + n\nprint(s)\n```\n\nQu'affiche ce programme ?",
      "options": [
        {
          "text": "`30`",
          "correct": true,
          "feedback": "Bonne réponse : 2, 4, 6, 8 et 10 font 30.\n"
        },
        {
          "text": "`25`",
          "correct": false,
          "feedback": "Erreur : 25 est la somme des impairs de 1 à 9. La condition\nretient les pairs.\n"
        },
        {
          "text": "`55`",
          "correct": false,
          "feedback": "Erreur : 55 serait la somme de tous les entiers de 1 à 10, sans\nla condition.\n"
        },
        {
          "text": "`20`",
          "correct": false,
          "feedback": "Erreur : 10 est bien parcouru, `range(1, 11)` va jusqu'à 10.\n"
        }
      ],
      "explanation": "Accumulateur et condition se combinent : on n'ajoute une valeur que\nsi elle vérifie le test. C'est le schéma d'une somme sélective.",
      "variants": [
        {
          "statement": "```python\ns = 0\nfor n in range(1, 11):\n    if n % 2 == 0:\n        s = s + n\nprint(s)\n```\n\nQu'affiche ce programme ?",
          "options": [
            {
              "text": "`30`",
              "correct": true,
              "feedback": "Bonne réponse : 2, 4, 6, 8 et 10 font 30.\n"
            },
            {
              "text": "`25`",
              "correct": false,
              "feedback": "Erreur : 25 est la somme des impairs de 1 à 9. La condition\nretient les pairs.\n"
            },
            {
              "text": "`55`",
              "correct": false,
              "feedback": "Erreur : 55 serait la somme de tous les entiers de 1 à 10, sans\nla condition.\n"
            },
            {
              "text": "`20`",
              "correct": false,
              "feedback": "Erreur : 10 est bien parcouru, `range(1, 11)` va jusqu'à 10.\n"
            }
          ],
          "explanation": "Accumulateur et condition se combinent : on n'ajoute une valeur que\nsi elle vérifie le test. C'est le schéma d'une somme sélective."
        },
        {
          "statement": "```python\ns = 0\nfor n in range(1, 13):\n    if n % 2 == 0:\n        s = s + n\nprint(s)\n```\n\nQu'affiche ce programme ?",
          "options": [
            {
              "text": "`42`",
              "correct": true,
              "feedback": "Bonne réponse : 2, 4, 6, 8, 10 et 12 font 42.\n"
            },
            {
              "text": "`36`",
              "correct": false,
              "feedback": "Erreur : 36 est la somme des impairs de 1 à 11. La condition\nretient les pairs.\n"
            },
            {
              "text": "`78`",
              "correct": false,
              "feedback": "Erreur : 78 serait la somme de tous les entiers de 1 à 12, sans\nla condition.\n"
            },
            {
              "text": "`30`",
              "correct": false,
              "feedback": "Erreur : 12 est bien parcouru, `range(1, 13)` va jusqu'à 12.\n"
            }
          ],
          "explanation": "Accumulateur et condition se combinent : on n'ajoute une valeur que\nsi elle vérifie le test. C'est le schéma d'une somme sélective."
        },
        {
          "statement": "```python\ns = 0\nfor n in range(1, 21):\n    if n % 2 == 0:\n        s = s + n\nprint(s)\n```\n\nQu'affiche ce programme ?",
          "options": [
            {
              "text": "`110`",
              "correct": true,
              "feedback": "Bonne réponse : 2, 4, 6, 8, 10, 12, 14, 16, 18 et 20 font 110.\n"
            },
            {
              "text": "`100`",
              "correct": false,
              "feedback": "Erreur : 100 est la somme des impairs de 1 à 19. La condition\nretient les pairs.\n"
            },
            {
              "text": "`210`",
              "correct": false,
              "feedback": "Erreur : 210 serait la somme de tous les entiers de 1 à 20, sans\nla condition.\n"
            },
            {
              "text": "`90`",
              "correct": false,
              "feedback": "Erreur : 20 est bien parcouru, `range(1, 21)` va jusqu'à 20.\n"
            }
          ],
          "explanation": "Accumulateur et condition se combinent : on n'ajoute une valeur que\nsi elle vérifie le test. C'est le schéma d'une somme sélective."
        }
      ]
    },
    {
      "id": "q17",
      "difficulty": 3,
      "skills": [
        "maximum",
        "trace"
      ],
      "title": "Chercher un maximum",
      "statement": "```python\nmaxi = 0\nfor x in range(1, 6):\n    valeur = x * (6 - x)\n    if valeur > maxi:\n        maxi = valeur\nprint(maxi)\n```\n\nQu'affiche ce programme ?",
      "options": [
        {
          "text": "`9`",
          "correct": true,
          "feedback": "Bonne réponse : les valeurs calculées sont 5, 8, 9, 8 et 5. La\nplus grande est 9, atteinte pour `x` égal à 3.\n"
        },
        {
          "text": "`8`",
          "correct": false,
          "feedback": "Erreur : 8 est dépassé par 9 au tour numéro 3.\n"
        },
        {
          "text": "`5`",
          "correct": false,
          "feedback": "Erreur : 5 est la dernière valeur calculée, mais `maxi` garde la\nplus grande rencontrée.\n"
        },
        {
          "text": "`6`",
          "correct": false,
          "feedback": "Erreur : 6 n'est jamais une valeur de `x * (6 - x)`.\n"
        }
      ],
      "explanation": "Pour trouver un maximum, on garde une variable mise à jour chaque\nfois qu'une valeur la dépasse. À la fin, elle contient la plus\ngrande valeur rencontrée.",
      "variants": [
        {
          "statement": "```python\nmaxi = 0\nfor x in range(1, 6):\n    valeur = x * (6 - x)\n    if valeur > maxi:\n        maxi = valeur\nprint(maxi)\n```\n\nQu'affiche ce programme ?",
          "options": [
            {
              "text": "`9`",
              "correct": true,
              "feedback": "Bonne réponse : les valeurs calculées sont 5, 8, 9, 8 et 5. La\nplus grande est 9, atteinte pour `x` égal à 3.\n"
            },
            {
              "text": "`8`",
              "correct": false,
              "feedback": "Erreur : 8 est dépassé par 9 au tour numéro 3.\n"
            },
            {
              "text": "`5`",
              "correct": false,
              "feedback": "Erreur : 5 est la dernière valeur calculée, mais `maxi` garde la\nplus grande rencontrée.\n"
            },
            {
              "text": "`6`",
              "correct": false,
              "feedback": "Erreur : 6 n'est jamais une valeur de `x * (6 - x)`.\n"
            }
          ],
          "explanation": "Pour trouver un maximum, on garde une variable mise à jour chaque\nfois qu'une valeur la dépasse. À la fin, elle contient la plus\ngrande valeur rencontrée."
        },
        {
          "statement": "```python\nmaxi = 0\nfor x in range(1, 8):\n    valeur = x * (8 - x)\n    if valeur > maxi:\n        maxi = valeur\nprint(maxi)\n```\n\nQu'affiche ce programme ?",
          "options": [
            {
              "text": "`16`",
              "correct": true,
              "feedback": "Bonne réponse : les valeurs calculées sont 7, 12, 15, 16, 15, 12 et 7. La\nplus grande est 16, atteinte pour `x` égal à 4.\n"
            },
            {
              "text": "`15`",
              "correct": false,
              "feedback": "Erreur : 15 est dépassé par 16 au tour numéro 4.\n"
            },
            {
              "text": "`7`",
              "correct": false,
              "feedback": "Erreur : 7 est la dernière valeur calculée, mais `maxi` garde la\nplus grande rencontrée.\n"
            },
            {
              "text": "`8`",
              "correct": false,
              "feedback": "Erreur : 8 n'est jamais une valeur de `x * (8 - x)`.\n"
            }
          ],
          "explanation": "Pour trouver un maximum, on garde une variable mise à jour chaque\nfois qu'une valeur la dépasse. À la fin, elle contient la plus\ngrande valeur rencontrée."
        },
        {
          "statement": "```python\nmaxi = 0\nfor x in range(1, 10):\n    valeur = x * (10 - x)\n    if valeur > maxi:\n        maxi = valeur\nprint(maxi)\n```\n\nQu'affiche ce programme ?",
          "options": [
            {
              "text": "`25`",
              "correct": true,
              "feedback": "Bonne réponse : les valeurs calculées sont 9, 16, 21, 24, 25, 24, 21, 16 et 9. La\nplus grande est 25, atteinte pour `x` égal à 5.\n"
            },
            {
              "text": "`24`",
              "correct": false,
              "feedback": "Erreur : 24 est dépassé par 25 au tour numéro 5.\n"
            },
            {
              "text": "`9`",
              "correct": false,
              "feedback": "Erreur : 9 est la dernière valeur calculée, mais `maxi` garde la\nplus grande rencontrée.\n"
            },
            {
              "text": "`10`",
              "correct": false,
              "feedback": "Erreur : 10 n'est jamais une valeur de `x * (10 - x)`.\n"
            }
          ],
          "explanation": "Pour trouver un maximum, on garde une variable mise à jour chaque\nfois qu'une valeur la dépasse. À la fin, elle contient la plus\ngrande valeur rencontrée."
        }
      ]
    },
    {
      "id": "q18",
      "difficulty": 2,
      "skills": [
        "for",
        "range",
        "trace"
      ],
      "title": "Un compte à rebours",
      "statement": "```python\nfor t in range(3, 0, -1):\n    print(t)\nprint(\"Partez\")\n```\n\nQu'affiche ce programme ?",
      "options": [
        {
          "text": "3, 2, 1 puis `Partez`",
          "correct": true,
          "feedback": "Bonne réponse : le pas -1 fait descendre de 3 à 1, la borne 0\nétant exclue, puis la ligne hors de la boucle s'exécute.\n"
        },
        {
          "text": "3, 2, 1, 0 puis `Partez`",
          "correct": false,
          "feedback": "Erreur : la borne 0 est exclue, même en descendant.\n"
        },
        {
          "text": "2, 1, 0 puis `Partez`",
          "correct": false,
          "feedback": "Erreur : le départ est le premier argument, 3.\n"
        },
        {
          "text": "`Partez` seulement",
          "correct": false,
          "feedback": "Erreur : `range(3, 0, -1)` fournit bien trois valeurs.\n"
        }
      ],
      "explanation": "Un pas négatif fait décroître la variable de boucle. Les règles sont\ninchangées : départ inclus, borne exclue."
    },
    {
      "id": "q19",
      "difficulty": 3,
      "skills": [
        "for",
        "accumulateur",
        "chaine"
      ],
      "title": "Construire une chaîne",
      "statement": "```python\nmot = \"\"\nfor c in \"abc\":\n    mot = c + mot\nprint(mot)\n```\n\nQu'affiche ce programme ?",
      "options": [
        {
          "text": "`cba`",
          "correct": true,
          "feedback": "Bonne réponse : chaque caractère est placé devant ce qui est\ndéjà construit : `a`, puis `ba`, puis `cba`.\n"
        },
        {
          "text": "`abc`",
          "correct": false,
          "feedback": "Erreur : ce serait le résultat de `mot = mot + c`, qui ajoute à\nla fin.\n"
        },
        {
          "text": "`abcabc`",
          "correct": false,
          "feedback": "Erreur : chaque tour n'ajoute qu'un caractère.\n"
        },
        {
          "text": "`ccc`",
          "correct": false,
          "feedback": "Erreur : `mot` conserve les caractères précédents.\n"
        }
      ],
      "explanation": "Une chaîne peut servir d'accumulateur : on part de la chaîne vide et\non concatène à chaque tour. L'ordre de la concaténation décide du\nsens de la chaîne obtenue."
    },
    {
      "id": "q20",
      "difficulty": 2,
      "skills": [
        "for",
        "range"
      ],
      "title": "Un range vide",
      "statement": "```python\nfor i in range(5, 5):\n    print(i)\nprint(\"Fin\")\n```\n\nQu'affiche ce programme ?",
      "options": [
        {
          "text": "`Fin` seulement",
          "correct": true,
          "feedback": "Bonne réponse : `range(5, 5)` ne contient aucune valeur, la\nboucle ne fait aucun tour, et le programme continue.\n"
        },
        {
          "text": "`5` puis `Fin`",
          "correct": false,
          "feedback": "Erreur : la borne 5 est exclue, il ne reste rien à parcourir.\n"
        },
        {
          "text": "Une erreur, un `range` ne peut pas être vide",
          "correct": false,
          "feedback": "Erreur : un `range` vide est parfaitement valable, la boucle\nest simplement sautée.\n"
        },
        {
          "text": "0, 1, 2, 3, 4 puis `Fin`",
          "correct": false,
          "feedback": "Erreur : ce serait `range(5)`. Avec deux arguments, le départ\nest 5.\n"
        }
      ],
      "explanation": "Une boucle `for` sur un `range` vide ne s'exécute pas du tout, sans\nerreur. C'est un cas à prévoir quand les bornes viennent d'un calcul."
    },
    {
      "id": "q21",
      "difficulty": 1,
      "skills": [
        "for",
        "range",
        "repetition"
      ],
      "title": "Un message répété",
      "statement": "Combien de fois ce programme affiche-t-il `hop` ?\n```python\nfor i in range(3):\n    print(\"hop\")\n```",
      "options": [
        {
          "text": "3 fois",
          "correct": true,
          "feedback": "Bonne réponse : `range(3)` fournit 3 valeurs, de 0 à 2,\ndonc le corps de la boucle s'exécute 3 fois.\n"
        },
        {
          "text": "2 fois",
          "correct": false,
          "feedback": "Erreur : `range(3)` s'arrête avant 3, mais commence à 0, ce\nqui fait bien 3 valeurs.\n"
        },
        {
          "text": "4 fois",
          "correct": false,
          "feedback": "Erreur : la valeur 3 elle-même n'est pas comprise dans\n`range(3)`.\n"
        },
        {
          "text": "Une seule fois, `i` n'étant pas utilisé",
          "correct": false,
          "feedback": "Erreur : la boucle se répète même si `i` ne sert pas dans le\ncorps.\n"
        }
      ],
      "explanation": "`range(n)` produit n valeurs, et le corps de la boucle est exécuté\nune fois pour chacune.",
      "variants": [
        {
          "statement": "Combien de fois ce programme affiche-t-il `hop` ?\n```python\nfor i in range(3):\n    print(\"hop\")\n```",
          "options": [
            {
              "text": "3 fois",
              "correct": true,
              "feedback": "Bonne réponse : `range(3)` fournit 3 valeurs, de 0 à 2,\ndonc le corps de la boucle s'exécute 3 fois.\n"
            },
            {
              "text": "2 fois",
              "correct": false,
              "feedback": "Erreur : `range(3)` s'arrête avant 3, mais commence à 0, ce\nqui fait bien 3 valeurs.\n"
            },
            {
              "text": "4 fois",
              "correct": false,
              "feedback": "Erreur : la valeur 3 elle-même n'est pas comprise dans\n`range(3)`.\n"
            },
            {
              "text": "Une seule fois, `i` n'étant pas utilisé",
              "correct": false,
              "feedback": "Erreur : la boucle se répète même si `i` ne sert pas dans le\ncorps.\n"
            }
          ],
          "explanation": "`range(n)` produit n valeurs, et le corps de la boucle est exécuté\nune fois pour chacune."
        },
        {
          "statement": "Combien de fois ce programme affiche-t-il `hop` ?\n```python\nfor i in range(5):\n    print(\"hop\")\n```",
          "options": [
            {
              "text": "5 fois",
              "correct": true,
              "feedback": "Bonne réponse : `range(5)` fournit 5 valeurs, de 0 à 4,\ndonc le corps de la boucle s'exécute 5 fois.\n"
            },
            {
              "text": "4 fois",
              "correct": false,
              "feedback": "Erreur : `range(5)` s'arrête avant 5, mais commence à 0, ce\nqui fait bien 5 valeurs.\n"
            },
            {
              "text": "6 fois",
              "correct": false,
              "feedback": "Erreur : la valeur 5 elle-même n'est pas comprise dans\n`range(5)`.\n"
            },
            {
              "text": "Une seule fois, `i` n'étant pas utilisé",
              "correct": false,
              "feedback": "Erreur : la boucle se répète même si `i` ne sert pas dans le\ncorps.\n"
            }
          ],
          "explanation": "`range(n)` produit n valeurs, et le corps de la boucle est exécuté\nune fois pour chacune."
        },
        {
          "statement": "Combien de fois ce programme affiche-t-il `hop` ?\n```python\nfor i in range(4):\n    print(\"hop\")\n```",
          "options": [
            {
              "text": "4 fois",
              "correct": true,
              "feedback": "Bonne réponse : `range(4)` fournit 4 valeurs, de 0 à 3,\ndonc le corps de la boucle s'exécute 4 fois.\n"
            },
            {
              "text": "3 fois",
              "correct": false,
              "feedback": "Erreur : `range(4)` s'arrête avant 4, mais commence à 0, ce\nqui fait bien 4 valeurs.\n"
            },
            {
              "text": "5 fois",
              "correct": false,
              "feedback": "Erreur : la valeur 4 elle-même n'est pas comprise dans\n`range(4)`.\n"
            },
            {
              "text": "Une seule fois, `i` n'étant pas utilisé",
              "correct": false,
              "feedback": "Erreur : la boucle se répète même si `i` ne sert pas dans le\ncorps.\n"
            }
          ],
          "explanation": "`range(n)` produit n valeurs, et le corps de la boucle est exécuté\nune fois pour chacune."
        }
      ]
    },
    {
      "id": "q22",
      "difficulty": 1,
      "skills": [
        "for",
        "range",
        "calcul"
      ],
      "title": "Une table de multiplication partielle",
      "statement": "Qu'affiche ce programme, les valeurs étant lues ligne par ligne ?\n```python\nfor i in range(1, 4):\n    print(i * 10)\n```",
      "options": [
        {
          "text": "`10 20 30`",
          "correct": true,
          "feedback": "Bonne réponse : `i` prend les valeurs 1, 2 et 3, et chacune est\nmultipliée par 10.\n"
        },
        {
          "text": "`10 20 30 40`",
          "correct": false,
          "feedback": "Erreur : la borne 4 est exclue, `i` ne la prend jamais.\n"
        },
        {
          "text": "`0 10 20`",
          "correct": false,
          "feedback": "Erreur : `range(1, 4)` commence à 1, pas à 0.\n"
        },
        {
          "text": "`1 2 3`",
          "correct": false,
          "feedback": "Erreur : c'est `i * 10` qui est affiché, pas `i`.\n"
        }
      ],
      "explanation": "`range(1, 4)` donne 1, 2, 3 : la première borne est incluse, la\nseconde exclue.",
      "variants": [
        {
          "statement": "Qu'affiche ce programme, les valeurs étant lues ligne par ligne ?\n```python\nfor i in range(1, 4):\n    print(i * 10)\n```",
          "options": [
            {
              "text": "`10 20 30`",
              "correct": true,
              "feedback": "Bonne réponse : `i` prend les valeurs 1, 2 et 3, et chacune est\nmultipliée par 10.\n"
            },
            {
              "text": "`10 20 30 40`",
              "correct": false,
              "feedback": "Erreur : la borne 4 est exclue, `i` ne la prend jamais.\n"
            },
            {
              "text": "`0 10 20`",
              "correct": false,
              "feedback": "Erreur : `range(1, 4)` commence à 1, pas à 0.\n"
            },
            {
              "text": "`1 2 3`",
              "correct": false,
              "feedback": "Erreur : c'est `i * 10` qui est affiché, pas `i`.\n"
            }
          ],
          "explanation": "`range(1, 4)` donne 1, 2, 3 : la première borne est incluse, la\nseconde exclue."
        },
        {
          "statement": "Qu'affiche ce programme, les valeurs étant lues ligne par ligne ?\n```python\nfor i in range(1, 4):\n    print(i * 5)\n```",
          "options": [
            {
              "text": "`5 10 15`",
              "correct": true,
              "feedback": "Bonne réponse : `i` prend les valeurs 1, 2 et 3, et chacune est\nmultipliée par 5.\n"
            },
            {
              "text": "`5 10 15 20`",
              "correct": false,
              "feedback": "Erreur : la borne 4 est exclue, `i` ne la prend jamais.\n"
            },
            {
              "text": "`0 5 10`",
              "correct": false,
              "feedback": "Erreur : `range(1, 4)` commence à 1, pas à 0.\n"
            },
            {
              "text": "`1 2 3`",
              "correct": false,
              "feedback": "Erreur : c'est `i * 5` qui est affiché, pas `i`.\n"
            }
          ],
          "explanation": "`range(1, 4)` donne 1, 2, 3 : la première borne est incluse, la\nseconde exclue."
        },
        {
          "statement": "Qu'affiche ce programme, les valeurs étant lues ligne par ligne ?\n```python\nfor i in range(1, 4):\n    print(i * 2)\n```",
          "options": [
            {
              "text": "`2 4 6`",
              "correct": true,
              "feedback": "Bonne réponse : `i` prend les valeurs 1, 2 et 3, et chacune est\nmultipliée par 2.\n"
            },
            {
              "text": "`2 4 6 8`",
              "correct": false,
              "feedback": "Erreur : la borne 4 est exclue, `i` ne la prend jamais.\n"
            },
            {
              "text": "`0 2 4`",
              "correct": false,
              "feedback": "Erreur : `range(1, 4)` commence à 1, pas à 0.\n"
            },
            {
              "text": "`1 2 3`",
              "correct": false,
              "feedback": "Erreur : c'est `i * 2` qui est affiché, pas `i`.\n"
            }
          ],
          "explanation": "`range(1, 4)` donne 1, 2, 3 : la première borne est incluse, la\nseconde exclue."
        }
      ]
    },
    {
      "id": "q23",
      "difficulty": 2,
      "skills": [
        "for",
        "accumulateur"
      ],
      "title": "Un accumulateur qui avance de deux en deux",
      "statement": "Qu'affiche ce programme ?\n```python\ns = 0\nfor i in range(3):\n    s = s + 2\nprint(s)\n```",
      "options": [
        {
          "text": "`6`",
          "correct": true,
          "feedback": "Bonne réponse : la boucle tourne 3 fois et ajoute 2 à chaque\ntour, soit 6 au total.\n"
        },
        {
          "text": "`3`",
          "correct": false,
          "feedback": "Erreur : 3 est le nombre de tours, mais chaque tour ajoute 2.\n"
        },
        {
          "text": "`2`",
          "correct": false,
          "feedback": "Erreur : `s` grandit à chaque tour, il ne reste pas à 2.\n"
        },
        {
          "text": "`5`",
          "correct": false,
          "feedback": "Erreur : il ne s'agit pas d'ajouter 2 une fois à 3, mais\nd'ajouter 2 à chacun des 3 tours.\n"
        }
      ],
      "explanation": "Une boucle qui ajoute une constante calcule une multiplication :\n3 tours de `+ 2` donnent 6.",
      "variants": [
        {
          "statement": "Qu'affiche ce programme ?\n```python\ns = 0\nfor i in range(3):\n    s = s + 2\nprint(s)\n```",
          "options": [
            {
              "text": "`6`",
              "correct": true,
              "feedback": "Bonne réponse : la boucle tourne 3 fois et ajoute 2 à chaque\ntour, soit 6 au total.\n"
            },
            {
              "text": "`3`",
              "correct": false,
              "feedback": "Erreur : 3 est le nombre de tours, mais chaque tour ajoute 2.\n"
            },
            {
              "text": "`2`",
              "correct": false,
              "feedback": "Erreur : `s` grandit à chaque tour, il ne reste pas à 2.\n"
            },
            {
              "text": "`5`",
              "correct": false,
              "feedback": "Erreur : il ne s'agit pas d'ajouter 2 une fois à 3, mais\nd'ajouter 2 à chacun des 3 tours.\n"
            }
          ],
          "explanation": "Une boucle qui ajoute une constante calcule une multiplication :\n3 tours de `+ 2` donnent 6."
        },
        {
          "statement": "Qu'affiche ce programme ?\n```python\ns = 0\nfor i in range(5):\n    s = s + 2\nprint(s)\n```",
          "options": [
            {
              "text": "`10`",
              "correct": true,
              "feedback": "Bonne réponse : la boucle tourne 5 fois et ajoute 2 à chaque\ntour, soit 10 au total.\n"
            },
            {
              "text": "`5`",
              "correct": false,
              "feedback": "Erreur : 5 est le nombre de tours, mais chaque tour ajoute 2.\n"
            },
            {
              "text": "`2`",
              "correct": false,
              "feedback": "Erreur : `s` grandit à chaque tour, il ne reste pas à 2.\n"
            },
            {
              "text": "`7`",
              "correct": false,
              "feedback": "Erreur : il ne s'agit pas d'ajouter 2 une fois à 5, mais\nd'ajouter 2 à chacun des 5 tours.\n"
            }
          ],
          "explanation": "Une boucle qui ajoute une constante calcule une multiplication :\n5 tours de `+ 2` donnent 10."
        },
        {
          "statement": "Qu'affiche ce programme ?\n```python\ns = 0\nfor i in range(7):\n    s = s + 2\nprint(s)\n```",
          "options": [
            {
              "text": "`14`",
              "correct": true,
              "feedback": "Bonne réponse : la boucle tourne 7 fois et ajoute 2 à chaque\ntour, soit 14 au total.\n"
            },
            {
              "text": "`7`",
              "correct": false,
              "feedback": "Erreur : 7 est le nombre de tours, mais chaque tour ajoute 2.\n"
            },
            {
              "text": "`2`",
              "correct": false,
              "feedback": "Erreur : `s` grandit à chaque tour, il ne reste pas à 2.\n"
            },
            {
              "text": "`9`",
              "correct": false,
              "feedback": "Erreur : il ne s'agit pas d'ajouter 2 une fois à 7, mais\nd'ajouter 2 à chacun des 7 tours.\n"
            }
          ],
          "explanation": "Une boucle qui ajoute une constante calcule une multiplication :\n7 tours de `+ 2` donnent 14."
        }
      ]
    },
    {
      "id": "q24",
      "difficulty": 2,
      "skills": [
        "for",
        "condition",
        "modulo"
      ],
      "title": "Les impairs d'une plage",
      "statement": "Qu'affiche ce programme, les valeurs étant lues ligne par ligne ?\n```python\nfor i in range(5):\n    if i % 2 == 1:\n        print(i)\n```",
      "options": [
        {
          "text": "`1 3`",
          "correct": true,
          "feedback": "Bonne réponse : seules les valeurs dont le reste par 2 vaut 1,\nles impairs, sont affichées, et 5 est exclu de la plage.\n"
        },
        {
          "text": "`1 3 5`",
          "correct": false,
          "feedback": "Erreur : `range(5)` s'arrête à 4, la valeur 5 n'est\njamais testée.\n"
        },
        {
          "text": "`0 2 4`",
          "correct": false,
          "feedback": "Erreur : `i % 2 == 1` retient les impairs, pas les pairs.\n"
        },
        {
          "text": "`0 1 2 3 4`",
          "correct": false,
          "feedback": "Erreur : le `if` filtre les valeurs, toutes ne sont pas\naffichées.\n"
        }
      ],
      "explanation": "Un `if` dans une boucle sélectionne certains tours. Ici, le reste\nde la division par 2 reconnaît les impairs.",
      "variants": [
        {
          "statement": "Qu'affiche ce programme, les valeurs étant lues ligne par ligne ?\n```python\nfor i in range(5):\n    if i % 2 == 1:\n        print(i)\n```",
          "options": [
            {
              "text": "`1 3`",
              "correct": true,
              "feedback": "Bonne réponse : seules les valeurs dont le reste par 2 vaut 1,\nles impairs, sont affichées, et 5 est exclu de la plage.\n"
            },
            {
              "text": "`1 3 5`",
              "correct": false,
              "feedback": "Erreur : `range(5)` s'arrête à 4, la valeur 5 n'est\njamais testée.\n"
            },
            {
              "text": "`0 2 4`",
              "correct": false,
              "feedback": "Erreur : `i % 2 == 1` retient les impairs, pas les pairs.\n"
            },
            {
              "text": "`0 1 2 3 4`",
              "correct": false,
              "feedback": "Erreur : le `if` filtre les valeurs, toutes ne sont pas\naffichées.\n"
            }
          ],
          "explanation": "Un `if` dans une boucle sélectionne certains tours. Ici, le reste\nde la division par 2 reconnaît les impairs."
        },
        {
          "statement": "Qu'affiche ce programme, les valeurs étant lues ligne par ligne ?\n```python\nfor i in range(9):\n    if i % 2 == 1:\n        print(i)\n```",
          "options": [
            {
              "text": "`1 3 5 7`",
              "correct": true,
              "feedback": "Bonne réponse : seules les valeurs dont le reste par 2 vaut 1,\nles impairs, sont affichées, et 9 est exclu de la plage.\n"
            },
            {
              "text": "`1 3 5 7 9`",
              "correct": false,
              "feedback": "Erreur : `range(9)` s'arrête à 8, la valeur 9 n'est\njamais testée.\n"
            },
            {
              "text": "`0 2 4 6 8`",
              "correct": false,
              "feedback": "Erreur : `i % 2 == 1` retient les impairs, pas les pairs.\n"
            },
            {
              "text": "`0 1 2 3 4 5 6 7 8`",
              "correct": false,
              "feedback": "Erreur : le `if` filtre les valeurs, toutes ne sont pas\naffichées.\n"
            }
          ],
          "explanation": "Un `if` dans une boucle sélectionne certains tours. Ici, le reste\nde la division par 2 reconnaît les impairs."
        },
        {
          "statement": "Qu'affiche ce programme, les valeurs étant lues ligne par ligne ?\n```python\nfor i in range(7):\n    if i % 2 == 1:\n        print(i)\n```",
          "options": [
            {
              "text": "`1 3 5`",
              "correct": true,
              "feedback": "Bonne réponse : seules les valeurs dont le reste par 2 vaut 1,\nles impairs, sont affichées, et 7 est exclu de la plage.\n"
            },
            {
              "text": "`1 3 5 7`",
              "correct": false,
              "feedback": "Erreur : `range(7)` s'arrête à 6, la valeur 7 n'est\njamais testée.\n"
            },
            {
              "text": "`0 2 4 6`",
              "correct": false,
              "feedback": "Erreur : `i % 2 == 1` retient les impairs, pas les pairs.\n"
            },
            {
              "text": "`0 1 2 3 4 5 6`",
              "correct": false,
              "feedback": "Erreur : le `if` filtre les valeurs, toutes ne sont pas\naffichées.\n"
            }
          ],
          "explanation": "Un `if` dans une boucle sélectionne certains tours. Ici, le reste\nde la division par 2 reconnaît les impairs."
        }
      ]
    },
    {
      "id": "q25",
      "difficulty": 2,
      "skills": [
        "for",
        "compteur",
        "condition"
      ],
      "title": "Compter au-delà d'un seuil",
      "statement": "Qu'affiche ce programme ?\n```python\nn = 0\nfor i in range(10):\n    if i > 6:\n        n = n + 1\nprint(n)\n```",
      "options": [
        {
          "text": "`3`",
          "correct": true,
          "feedback": "Bonne réponse : les valeurs de `range(10)` strictement\nsupérieures à 6 vont de 7 à 9, il y en a 3.\n"
        },
        {
          "text": "`4`",
          "correct": false,
          "feedback": "Erreur : `i > 6` exclut 6 lui-même, et `range(10)` s'arrête\nà 9.\n"
        },
        {
          "text": "`6`",
          "correct": false,
          "feedback": "Erreur : 6 est le seuil, pas le nombre de valeurs qui le\ndépassent.\n"
        },
        {
          "text": "`10`",
          "correct": false,
          "feedback": "Erreur : seules les valeurs qui vérifient la condition sont\ncomptées.\n"
        }
      ],
      "explanation": "Un compteur n'avance que lorsque la condition est vraie. Compter\nles tours retenus demande d'écrire la liste des valeurs qui\npassent le test.",
      "variants": [
        {
          "statement": "Qu'affiche ce programme ?\n```python\nn = 0\nfor i in range(10):\n    if i > 6:\n        n = n + 1\nprint(n)\n```",
          "options": [
            {
              "text": "`3`",
              "correct": true,
              "feedback": "Bonne réponse : les valeurs de `range(10)` strictement\nsupérieures à 6 vont de 7 à 9, il y en a 3.\n"
            },
            {
              "text": "`4`",
              "correct": false,
              "feedback": "Erreur : `i > 6` exclut 6 lui-même, et `range(10)` s'arrête\nà 9.\n"
            },
            {
              "text": "`6`",
              "correct": false,
              "feedback": "Erreur : 6 est le seuil, pas le nombre de valeurs qui le\ndépassent.\n"
            },
            {
              "text": "`10`",
              "correct": false,
              "feedback": "Erreur : seules les valeurs qui vérifient la condition sont\ncomptées.\n"
            }
          ],
          "explanation": "Un compteur n'avance que lorsque la condition est vraie. Compter\nles tours retenus demande d'écrire la liste des valeurs qui\npassent le test."
        },
        {
          "statement": "Qu'affiche ce programme ?\n```python\nn = 0\nfor i in range(10):\n    if i > 3:\n        n = n + 1\nprint(n)\n```",
          "options": [
            {
              "text": "`6`",
              "correct": true,
              "feedback": "Bonne réponse : les valeurs de `range(10)` strictement\nsupérieures à 3 vont de 4 à 9, il y en a 6.\n"
            },
            {
              "text": "`7`",
              "correct": false,
              "feedback": "Erreur : `i > 3` exclut 3 lui-même, et `range(10)` s'arrête\nà 9.\n"
            },
            {
              "text": "`3`",
              "correct": false,
              "feedback": "Erreur : 3 est le seuil, pas le nombre de valeurs qui le\ndépassent.\n"
            },
            {
              "text": "`10`",
              "correct": false,
              "feedback": "Erreur : seules les valeurs qui vérifient la condition sont\ncomptées.\n"
            }
          ],
          "explanation": "Un compteur n'avance que lorsque la condition est vraie. Compter\nles tours retenus demande d'écrire la liste des valeurs qui\npassent le test."
        },
        {
          "statement": "Qu'affiche ce programme ?\n```python\nn = 0\nfor i in range(10):\n    if i > 8:\n        n = n + 1\nprint(n)\n```",
          "options": [
            {
              "text": "`1`",
              "correct": true,
              "feedback": "Bonne réponse : les valeurs de `range(10)` strictement\nsupérieures à 8 vont de 9 à 9, il y en a 1.\n"
            },
            {
              "text": "`2`",
              "correct": false,
              "feedback": "Erreur : `i > 8` exclut 8 lui-même, et `range(10)` s'arrête\nà 9.\n"
            },
            {
              "text": "`8`",
              "correct": false,
              "feedback": "Erreur : 8 est le seuil, pas le nombre de valeurs qui le\ndépassent.\n"
            },
            {
              "text": "`10`",
              "correct": false,
              "feedback": "Erreur : seules les valeurs qui vérifient la condition sont\ncomptées.\n"
            }
          ],
          "explanation": "Un compteur n'avance que lorsque la condition est vraie. Compter\nles tours retenus demande d'écrire la liste des valeurs qui\npassent le test."
        }
      ]
    },
    {
      "id": "q26",
      "difficulty": 2,
      "skills": [
        "for",
        "print",
        "carre"
      ],
      "title": "Des carrés ligne par ligne",
      "statement": "Qu'affiche ce programme ? Les lignes sont données séparées par des\nvirgules.\n```python\nfor i in range(3):\n    print(i, i * i)\n```",
      "options": [
        {
          "text": "`0 0, 1 1, 2 4`",
          "correct": true,
          "feedback": "Bonne réponse : pour chaque valeur de `i`, de 0 à 2, la ligne\naffiche `i` puis son carré.\n"
        },
        {
          "text": "`1 1, 2 4, 3 9`",
          "correct": false,
          "feedback": "Erreur : `range(3)` commence à 0 et exclut 3.\n"
        },
        {
          "text": "`0 0, 1 2, 2 4`",
          "correct": false,
          "feedback": "Erreur : `i * i` est le carré de `i`, pas son double.\n"
        },
        {
          "text": "`3 9`",
          "correct": false,
          "feedback": "Erreur : le `print` est dans la boucle, une ligne par tour est\naffichée.\n"
        }
      ],
      "explanation": "Un `print` dans la boucle produit une ligne par tour, avec les\nvaleurs calculées à ce tour.",
      "variants": [
        {
          "statement": "Qu'affiche ce programme ? Les lignes sont données séparées par des\nvirgules.\n```python\nfor i in range(3):\n    print(i, i * i)\n```",
          "options": [
            {
              "text": "`0 0, 1 1, 2 4`",
              "correct": true,
              "feedback": "Bonne réponse : pour chaque valeur de `i`, de 0 à 2, la ligne\naffiche `i` puis son carré.\n"
            },
            {
              "text": "`1 1, 2 4, 3 9`",
              "correct": false,
              "feedback": "Erreur : `range(3)` commence à 0 et exclut 3.\n"
            },
            {
              "text": "`0 0, 1 2, 2 4`",
              "correct": false,
              "feedback": "Erreur : `i * i` est le carré de `i`, pas son double.\n"
            },
            {
              "text": "`3 9`",
              "correct": false,
              "feedback": "Erreur : le `print` est dans la boucle, une ligne par tour est\naffichée.\n"
            }
          ],
          "explanation": "Un `print` dans la boucle produit une ligne par tour, avec les\nvaleurs calculées à ce tour."
        },
        {
          "statement": "Qu'affiche ce programme ? Les lignes sont données séparées par des\nvirgules.\n```python\nfor i in range(4):\n    print(i, i * i)\n```",
          "options": [
            {
              "text": "`0 0, 1 1, 2 4, 3 9`",
              "correct": true,
              "feedback": "Bonne réponse : pour chaque valeur de `i`, de 0 à 3, la ligne\naffiche `i` puis son carré.\n"
            },
            {
              "text": "`1 1, 2 4, 3 9, 4 16`",
              "correct": false,
              "feedback": "Erreur : `range(4)` commence à 0 et exclut 4.\n"
            },
            {
              "text": "`0 0, 1 2, 2 4, 3 6`",
              "correct": false,
              "feedback": "Erreur : `i * i` est le carré de `i`, pas son double.\n"
            },
            {
              "text": "`4 16`",
              "correct": false,
              "feedback": "Erreur : le `print` est dans la boucle, une ligne par tour est\naffichée.\n"
            }
          ],
          "explanation": "Un `print` dans la boucle produit une ligne par tour, avec les\nvaleurs calculées à ce tour."
        },
        {
          "statement": "Qu'affiche ce programme ? Les lignes sont données séparées par des\nvirgules.\n```python\nfor i in range(2):\n    print(i, i * i)\n```",
          "options": [
            {
              "text": "`0 0, 1 1`",
              "correct": true,
              "feedback": "Bonne réponse : pour chaque valeur de `i`, de 0 à 1, la ligne\naffiche `i` puis son carré.\n"
            },
            {
              "text": "`1 1, 2 4`",
              "correct": false,
              "feedback": "Erreur : `range(2)` commence à 0 et exclut 2.\n"
            },
            {
              "text": "`0 0, 1 2`",
              "correct": false,
              "feedback": "Erreur : `i * i` est le carré de `i`, pas son double.\n"
            },
            {
              "text": "`2 4`",
              "correct": false,
              "feedback": "Erreur : le `print` est dans la boucle, une ligne par tour est\naffichée.\n"
            }
          ],
          "explanation": "Un `print` dans la boucle produit une ligne par tour, avec les\nvaleurs calculées à ce tour."
        }
      ]
    },
    {
      "id": "q27",
      "difficulty": 3,
      "skills": [
        "for",
        "accumulateur",
        "calcul"
      ],
      "title": "Une somme de doubles",
      "statement": "Qu'affiche ce programme ?\n```python\ntotal = 0\nfor i in range(5):\n    total = total + i * 2\nprint(total)\n```",
      "options": [
        {
          "text": "`20`",
          "correct": true,
          "feedback": "Bonne réponse : les doubles de 0 à 4 s'additionnent : la\nsomme de 0 à 4 vaut 10, et son double 20.\n"
        },
        {
          "text": "`10`",
          "correct": false,
          "feedback": "Erreur : 10 est la somme des valeurs de `i` sans le\ndoublement.\n"
        },
        {
          "text": "`8`",
          "correct": false,
          "feedback": "Erreur : 8 est seulement la dernière valeur ajoutée,\n`total` accumule toutes les autres.\n"
        },
        {
          "text": "`0`",
          "correct": false,
          "feedback": "Erreur : `total` part de 0 mais grandit à chaque tour.\n"
        }
      ],
      "explanation": "Pour suivre un accumulateur, on note la valeur ajoutée à chaque\ntour et on additionne : ici 0, 2, 4, et ainsi de suite jusqu'à\n8.",
      "variants": [
        {
          "statement": "Qu'affiche ce programme ?\n```python\ntotal = 0\nfor i in range(5):\n    total = total + i * 2\nprint(total)\n```",
          "options": [
            {
              "text": "`20`",
              "correct": true,
              "feedback": "Bonne réponse : les doubles de 0 à 4 s'additionnent : la\nsomme de 0 à 4 vaut 10, et son double 20.\n"
            },
            {
              "text": "`10`",
              "correct": false,
              "feedback": "Erreur : 10 est la somme des valeurs de `i` sans le\ndoublement.\n"
            },
            {
              "text": "`8`",
              "correct": false,
              "feedback": "Erreur : 8 est seulement la dernière valeur ajoutée,\n`total` accumule toutes les autres.\n"
            },
            {
              "text": "`0`",
              "correct": false,
              "feedback": "Erreur : `total` part de 0 mais grandit à chaque tour.\n"
            }
          ],
          "explanation": "Pour suivre un accumulateur, on note la valeur ajoutée à chaque\ntour et on additionne : ici 0, 2, 4, et ainsi de suite jusqu'à\n8."
        },
        {
          "statement": "Qu'affiche ce programme ?\n```python\ntotal = 0\nfor i in range(7):\n    total = total + i * 2\nprint(total)\n```",
          "options": [
            {
              "text": "`42`",
              "correct": true,
              "feedback": "Bonne réponse : les doubles de 0 à 6 s'additionnent : la\nsomme de 0 à 6 vaut 21, et son double 42.\n"
            },
            {
              "text": "`21`",
              "correct": false,
              "feedback": "Erreur : 21 est la somme des valeurs de `i` sans le\ndoublement.\n"
            },
            {
              "text": "`12`",
              "correct": false,
              "feedback": "Erreur : 12 est seulement la dernière valeur ajoutée,\n`total` accumule toutes les autres.\n"
            },
            {
              "text": "`0`",
              "correct": false,
              "feedback": "Erreur : `total` part de 0 mais grandit à chaque tour.\n"
            }
          ],
          "explanation": "Pour suivre un accumulateur, on note la valeur ajoutée à chaque\ntour et on additionne : ici 0, 2, 4, et ainsi de suite jusqu'à\n12."
        },
        {
          "statement": "Qu'affiche ce programme ?\n```python\ntotal = 0\nfor i in range(6):\n    total = total + i * 2\nprint(total)\n```",
          "options": [
            {
              "text": "`30`",
              "correct": true,
              "feedback": "Bonne réponse : les doubles de 0 à 5 s'additionnent : la\nsomme de 0 à 5 vaut 15, et son double 30.\n"
            },
            {
              "text": "`15`",
              "correct": false,
              "feedback": "Erreur : 15 est la somme des valeurs de `i` sans le\ndoublement.\n"
            },
            {
              "text": "`10`",
              "correct": false,
              "feedback": "Erreur : 10 est seulement la dernière valeur ajoutée,\n`total` accumule toutes les autres.\n"
            },
            {
              "text": "`0`",
              "correct": false,
              "feedback": "Erreur : `total` part de 0 mais grandit à chaque tour.\n"
            }
          ],
          "explanation": "Pour suivre un accumulateur, on note la valeur ajoutée à chaque\ntour et on additionne : ici 0, 2, 4, et ainsi de suite jusqu'à\n10."
        }
      ]
    },
    {
      "id": "q28",
      "difficulty": 3,
      "skills": [
        "for",
        "condition",
        "modulo",
        "somme"
      ],
      "title": "La somme des multiples de trois",
      "statement": "Qu'affiche ce programme ?\n```python\ns = 0\nfor i in range(10):\n    if i % 3 == 0:\n        s = s + i\nprint(s)\n```",
      "options": [
        {
          "text": "`18`",
          "correct": true,
          "feedback": "Bonne réponse : seuls les multiples de 3 inférieurs à 10 sont\najoutés, 0 compris, et leur somme vaut 18.\n"
        },
        {
          "text": "`4`",
          "correct": false,
          "feedback": "Erreur : 4 est le nombre de multiples de 3 retenus, pas leur\nsomme.\n"
        },
        {
          "text": "`45`",
          "correct": false,
          "feedback": "Erreur : 45 est la somme de toutes les valeurs de\n`range(10)`, sans le filtre.\n"
        },
        {
          "text": "`10`",
          "correct": false,
          "feedback": "Erreur : 10 est la borne de la plage, elle n'est même pas\nparcourue.\n"
        }
      ],
      "explanation": "Filtre et accumulateur se combinent : le `if` choisit les valeurs,\nl'addition les cumule.",
      "variants": [
        {
          "statement": "Qu'affiche ce programme ?\n```python\ns = 0\nfor i in range(10):\n    if i % 3 == 0:\n        s = s + i\nprint(s)\n```",
          "options": [
            {
              "text": "`18`",
              "correct": true,
              "feedback": "Bonne réponse : seuls les multiples de 3 inférieurs à 10 sont\najoutés, 0 compris, et leur somme vaut 18.\n"
            },
            {
              "text": "`4`",
              "correct": false,
              "feedback": "Erreur : 4 est le nombre de multiples de 3 retenus, pas leur\nsomme.\n"
            },
            {
              "text": "`45`",
              "correct": false,
              "feedback": "Erreur : 45 est la somme de toutes les valeurs de\n`range(10)`, sans le filtre.\n"
            },
            {
              "text": "`10`",
              "correct": false,
              "feedback": "Erreur : 10 est la borne de la plage, elle n'est même pas\nparcourue.\n"
            }
          ],
          "explanation": "Filtre et accumulateur se combinent : le `if` choisit les valeurs,\nl'addition les cumule."
        },
        {
          "statement": "Qu'affiche ce programme ?\n```python\ns = 0\nfor i in range(13):\n    if i % 3 == 0:\n        s = s + i\nprint(s)\n```",
          "options": [
            {
              "text": "`30`",
              "correct": true,
              "feedback": "Bonne réponse : seuls les multiples de 3 inférieurs à 13 sont\najoutés, 0 compris, et leur somme vaut 30.\n"
            },
            {
              "text": "`5`",
              "correct": false,
              "feedback": "Erreur : 5 est le nombre de multiples de 3 retenus, pas leur\nsomme.\n"
            },
            {
              "text": "`78`",
              "correct": false,
              "feedback": "Erreur : 78 est la somme de toutes les valeurs de\n`range(13)`, sans le filtre.\n"
            },
            {
              "text": "`13`",
              "correct": false,
              "feedback": "Erreur : 13 est la borne de la plage, elle n'est même pas\nparcourue.\n"
            }
          ],
          "explanation": "Filtre et accumulateur se combinent : le `if` choisit les valeurs,\nl'addition les cumule."
        },
        {
          "statement": "Qu'affiche ce programme ?\n```python\ns = 0\nfor i in range(7):\n    if i % 3 == 0:\n        s = s + i\nprint(s)\n```",
          "options": [
            {
              "text": "`9`",
              "correct": true,
              "feedback": "Bonne réponse : seuls les multiples de 3 inférieurs à 7 sont\najoutés, 0 compris, et leur somme vaut 9.\n"
            },
            {
              "text": "`3`",
              "correct": false,
              "feedback": "Erreur : 3 est le nombre de multiples de 3 retenus, pas leur\nsomme.\n"
            },
            {
              "text": "`21`",
              "correct": false,
              "feedback": "Erreur : 21 est la somme de toutes les valeurs de\n`range(7)`, sans le filtre.\n"
            },
            {
              "text": "`7`",
              "correct": false,
              "feedback": "Erreur : 7 est la borne de la plage, elle n'est même pas\nparcourue.\n"
            }
          ],
          "explanation": "Filtre et accumulateur se combinent : le `if` choisit les valeurs,\nl'addition les cumule."
        }
      ]
    },
    {
      "id": "q29",
      "difficulty": 3,
      "skills": [
        "for",
        "chaine",
        "repetition"
      ],
      "title": "Un triangle d'étoiles",
      "statement": "Qu'affiche ce programme ? Les lignes sont données séparées par des\nvirgules.\n```python\nfor i in range(3):\n    print(\"*\" * (i + 1))\n```",
      "options": [
        {
          "text": "`*`, `**`, `***`",
          "correct": true,
          "feedback": "Bonne réponse : au tour `i`, la chaîne `\"*\"` est répétée\n`i + 1` fois, donc 1, puis 2, et ainsi de suite jusqu'à 3.\n"
        },
        {
          "text": "`***`, `***`, `***`",
          "correct": false,
          "feedback": "Erreur : le nombre d'étoiles dépend de `i`, il change à chaque\ntour.\n"
        },
        {
          "text": "`*`, `**`",
          "correct": false,
          "feedback": "Erreur : `range(3)` donne 3 tours, et le dernier affiche 3\nétoiles grâce au `+ 1`.\n"
        },
        {
          "text": "`* * *`",
          "correct": false,
          "feedback": "Erreur : chaque tour produit sa propre ligne, et `\"*\" * k`\ncolle les étoiles sans espace.\n"
        }
      ],
      "explanation": "Multiplier une chaîne par un entier la répète. Combiné à une\nboucle, cela dessine des figures ligne par ligne.",
      "variants": [
        {
          "statement": "Qu'affiche ce programme ? Les lignes sont données séparées par des\nvirgules.\n```python\nfor i in range(3):\n    print(\"*\" * (i + 1))\n```",
          "options": [
            {
              "text": "`*`, `**`, `***`",
              "correct": true,
              "feedback": "Bonne réponse : au tour `i`, la chaîne `\"*\"` est répétée\n`i + 1` fois, donc 1, puis 2, et ainsi de suite jusqu'à 3.\n"
            },
            {
              "text": "`***`, `***`, `***`",
              "correct": false,
              "feedback": "Erreur : le nombre d'étoiles dépend de `i`, il change à chaque\ntour.\n"
            },
            {
              "text": "`*`, `**`",
              "correct": false,
              "feedback": "Erreur : `range(3)` donne 3 tours, et le dernier affiche 3\nétoiles grâce au `+ 1`.\n"
            },
            {
              "text": "`* * *`",
              "correct": false,
              "feedback": "Erreur : chaque tour produit sa propre ligne, et `\"*\" * k`\ncolle les étoiles sans espace.\n"
            }
          ],
          "explanation": "Multiplier une chaîne par un entier la répète. Combiné à une\nboucle, cela dessine des figures ligne par ligne."
        },
        {
          "statement": "Qu'affiche ce programme ? Les lignes sont données séparées par des\nvirgules.\n```python\nfor i in range(4):\n    print(\"*\" * (i + 1))\n```",
          "options": [
            {
              "text": "`*`, `**`, `***`, `****`",
              "correct": true,
              "feedback": "Bonne réponse : au tour `i`, la chaîne `\"*\"` est répétée\n`i + 1` fois, donc 1, puis 2, et ainsi de suite jusqu'à 4.\n"
            },
            {
              "text": "`****`, `****`, `****`, `****`",
              "correct": false,
              "feedback": "Erreur : le nombre d'étoiles dépend de `i`, il change à chaque\ntour.\n"
            },
            {
              "text": "`*`, `**`, `***`",
              "correct": false,
              "feedback": "Erreur : `range(4)` donne 4 tours, et le dernier affiche 4\nétoiles grâce au `+ 1`.\n"
            },
            {
              "text": "`* * * *`",
              "correct": false,
              "feedback": "Erreur : chaque tour produit sa propre ligne, et `\"*\" * k`\ncolle les étoiles sans espace.\n"
            }
          ],
          "explanation": "Multiplier une chaîne par un entier la répète. Combiné à une\nboucle, cela dessine des figures ligne par ligne."
        },
        {
          "statement": "Qu'affiche ce programme ? Les lignes sont données séparées par des\nvirgules.\n```python\nfor i in range(2):\n    print(\"*\" * (i + 1))\n```",
          "options": [
            {
              "text": "`*`, `**`",
              "correct": true,
              "feedback": "Bonne réponse : au tour `i`, la chaîne `\"*\"` est répétée\n`i + 1` fois, donc 1, puis 2, et ainsi de suite jusqu'à 2.\n"
            },
            {
              "text": "`**`, `**`",
              "correct": false,
              "feedback": "Erreur : le nombre d'étoiles dépend de `i`, il change à chaque\ntour.\n"
            },
            {
              "text": "`*`",
              "correct": false,
              "feedback": "Erreur : `range(2)` donne 2 tours, et le dernier affiche 2\nétoiles grâce au `+ 1`.\n"
            },
            {
              "text": "`* *`",
              "correct": false,
              "feedback": "Erreur : chaque tour produit sa propre ligne, et `\"*\" * k`\ncolle les étoiles sans espace.\n"
            }
          ],
          "explanation": "Multiplier une chaîne par un entier la répète. Combiné à une\nboucle, cela dessine des figures ligne par ligne."
        }
      ]
    },
    {
      "id": "q30",
      "difficulty": 3,
      "skills": [
        "for",
        "accumulateur",
        "print"
      ],
      "title": "Des sommes affichées au fil de la boucle",
      "statement": "Qu'affiche ce programme, les valeurs étant lues ligne par ligne ?\n```python\ny = 0\nfor x in range(4):\n    y = y + x\n    print(y)\n```",
      "options": [
        {
          "text": "`0 1 3 6`",
          "correct": true,
          "feedback": "Bonne réponse : `y` cumule les valeurs de `x` et est affiché\naprès chaque ajout, d'où les sommes successives.\n"
        },
        {
          "text": "`0 1 2 3`",
          "correct": false,
          "feedback": "Erreur : c'est `y` qui est affiché, pas `x`.\n"
        },
        {
          "text": "`6`",
          "correct": false,
          "feedback": "Erreur : le `print` est dans la boucle, il y a une ligne par\ntour.\n"
        },
        {
          "text": "`1 3 6 10`",
          "correct": false,
          "feedback": "Erreur : `range(4)` commence à 0, donc la première somme vaut\n0.\n"
        }
      ],
      "explanation": "Afficher dans la boucle montre l'évolution de l'accumulateur ;\nafficher après la boucle ne montre que sa valeur finale.",
      "variants": [
        {
          "statement": "Qu'affiche ce programme, les valeurs étant lues ligne par ligne ?\n```python\ny = 0\nfor x in range(4):\n    y = y + x\n    print(y)\n```",
          "options": [
            {
              "text": "`0 1 3 6`",
              "correct": true,
              "feedback": "Bonne réponse : `y` cumule les valeurs de `x` et est affiché\naprès chaque ajout, d'où les sommes successives.\n"
            },
            {
              "text": "`0 1 2 3`",
              "correct": false,
              "feedback": "Erreur : c'est `y` qui est affiché, pas `x`.\n"
            },
            {
              "text": "`6`",
              "correct": false,
              "feedback": "Erreur : le `print` est dans la boucle, il y a une ligne par\ntour.\n"
            },
            {
              "text": "`1 3 6 10`",
              "correct": false,
              "feedback": "Erreur : `range(4)` commence à 0, donc la première somme vaut\n0.\n"
            }
          ],
          "explanation": "Afficher dans la boucle montre l'évolution de l'accumulateur ;\nafficher après la boucle ne montre que sa valeur finale."
        },
        {
          "statement": "Qu'affiche ce programme, les valeurs étant lues ligne par ligne ?\n```python\ny = 0\nfor x in range(5):\n    y = y + x\n    print(y)\n```",
          "options": [
            {
              "text": "`0 1 3 6 10`",
              "correct": true,
              "feedback": "Bonne réponse : `y` cumule les valeurs de `x` et est affiché\naprès chaque ajout, d'où les sommes successives.\n"
            },
            {
              "text": "`0 1 2 3 4`",
              "correct": false,
              "feedback": "Erreur : c'est `y` qui est affiché, pas `x`.\n"
            },
            {
              "text": "`10`",
              "correct": false,
              "feedback": "Erreur : le `print` est dans la boucle, il y a une ligne par\ntour.\n"
            },
            {
              "text": "`1 3 6 10 15`",
              "correct": false,
              "feedback": "Erreur : `range(5)` commence à 0, donc la première somme vaut\n0.\n"
            }
          ],
          "explanation": "Afficher dans la boucle montre l'évolution de l'accumulateur ;\nafficher après la boucle ne montre que sa valeur finale."
        },
        {
          "statement": "Qu'affiche ce programme, les valeurs étant lues ligne par ligne ?\n```python\ny = 0\nfor x in range(3):\n    y = y + x\n    print(y)\n```",
          "options": [
            {
              "text": "`0 1 3`",
              "correct": true,
              "feedback": "Bonne réponse : `y` cumule les valeurs de `x` et est affiché\naprès chaque ajout, d'où les sommes successives.\n"
            },
            {
              "text": "`0 1 2`",
              "correct": false,
              "feedback": "Erreur : c'est `y` qui est affiché, pas `x`.\n"
            },
            {
              "text": "`3`",
              "correct": false,
              "feedback": "Erreur : le `print` est dans la boucle, il y a une ligne par\ntour.\n"
            },
            {
              "text": "`1 3 6`",
              "correct": false,
              "feedback": "Erreur : `range(3)` commence à 0, donc la première somme vaut\n0.\n"
            }
          ],
          "explanation": "Afficher dans la boucle montre l'évolution de l'accumulateur ;\nafficher après la boucle ne montre que sa valeur finale."
        }
      ]
    }
  ]
}