<?xml version="1.0" encoding="UTF-8"?>
<quiz>
<question type="category">
  <category>
    <text>$course$/QCM de NSI/Première/Invariants et terminaison</text>
  </category>
  <info format="html">
    <text><![CDATA[<p>Preuve de correction et de terminaison d'une boucle :<br/>
invariant de boucle (propriété conservée à chaque<br/>
itération) et variant de boucle (quantité entière qui<br/>
décroît strictement). Application aux algorithmes<br/>
classiques (recherche, tri).</p>]]></text>
  </info>
</question>

<question type="multichoice">
  <name>
    <text>Invariants et terminaison — Q01 : Invariant de boucle</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Qu'est-ce qu'un <strong>invariant de boucle</strong> ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>L'invariant sert à prouver que la boucle calcule<br/>
bien ce qu'elle doit. À la sortie, l'invariant<br/>
combiné à la condition d'arrêt donne la<br/>
correction de l'algorithme.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Une exception levée pendant l'exécution de la boucle</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Une exception est une<br/>
erreur d'exécution. Un<br/>
invariant est, lui, une<br/>
propriété logique<br/>
maintenue tout au long<br/>
de la boucle.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Une variable dont la valeur ne change pas dans la boucle</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Trop restrictif : un invariant peut concerner<br/>
plusieurs variables ou des relations entre<br/>
elles.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Une propriété vraie au début et conservée à chaque itération de la boucle</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : c'est une propriété<br/>
mathématique qu'on prouve vraie avant la<br/>
boucle, puis qu'on prouve conservée à chaque<br/>
tour. Elle reste vraie à la sortie.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Une boucle qui ne se termine pas</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : une boucle infinie est un bug, pas<br/>
un invariant.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Invariants et terminaison — Q02 : Terminaison</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Qu'appelle-t-on <strong>terminaison</strong> d'un algorithme ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Distinction essentielle : un algorithme peut être<br/>
<strong>correct</strong> (donner le bon résultat <strong>s'il<br/>
termine</strong>) sans <strong>terminer</strong> (boucle infinie).<br/>
On veut prouver les deux propriétés.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Une variable globale nommée <code>fin</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>La terminaison est une<br/>
propriété mathématique<br/>
de l'algorithme, et non<br/>
le nom d'une variable<br/>
dans le code.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Le moment où l'utilisateur appuie sur Ctrl+C</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Plaisanterie : c'est une interruption<br/>
extérieure, pas la terminaison de<br/>
l'algorithme.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Le nom donné à la dernière instruction</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : la terminaison est une propriété<br/>
globale, pas une instruction particulière.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>La garantie que l'algorithme s'arrête après un nombre fini d'étapes, quelle que soit l'entrée</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : prouver la terminaison, c'est<br/>
montrer qu'aucune entrée valide ne fera<br/>
boucler indéfiniment l'algorithme.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Invariants et terminaison — Q03 : Variant de boucle</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Pour prouver la terminaison d'une boucle <code>while</code>,<br/>
on cherche un <strong>variant</strong>. Quelle propriété<br/>
doit-il avoir ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Variant typique : pour la dichotomie, c'est la<br/>
<strong>taille de l'intervalle</strong> <code>d - g</code> qui décroît<br/>
strictement. Pour <code>while x &gt; 0: x -= 1</code>, c'est<br/>
<code>x</code> lui-même.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Croître à chaque itération</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : un variant croissant ne prouve pas<br/>
la terminaison (la suite peut être<br/>
non-bornée).</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Être un entier (ou une quantité minorée) qui décroît strictement à chaque itération</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : si une quantité entière<br/>
décroît strictement et est minorée<br/>
(par exemple, par 0), elle ne peut décroître<br/>
qu'un nombre fini de fois.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Rester constant</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : un invariant, oui ; un variant,<br/>
non.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Être une chaîne de caractères qui change</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : un variant est une <strong>quantité<br/>
entière</strong> (ou minorée), pas une chaîne.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Invariants et terminaison — Q04 : Exemple : recherche linéaire</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Dans une recherche linéaire avec <code>for i in<br/>
range(len(liste))</code>, quel est l'<strong>invariant</strong> à<br/>
l'entrée du tour <code>i</code> ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Combiner invariant + condition de sortie : à la<br/>
sortie (i = n et pas de return), invariant + (i<br/>
= n) ⇒ « cible absente ». L'invariant est l'âme<br/>
de la preuve.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>La cible est plus grande que tous les éléments testés</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : aucune relation d'ordre n'intervient<br/>
dans une recherche linéaire générale.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>La cible n'est dans aucune position de la liste</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Trop fort : on ne sait pas encore si la<br/>
cible est plus loin.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>La liste est triée</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : la recherche linéaire n'a pas besoin<br/>
du tri.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>La cible n'a pas été trouvée dans <code>liste[0..i-1]</code> (notation algorithmique pour les éléments déjà parcourus ; en Python : <code>liste[:i]</code>)</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : à l'entrée de l'itération<br/>
<code>i</code>, on a déjà testé les indices 0 à i-1 et<br/>
aucun n'a satisfait le critère. Si on en<br/>
avait trouvé un, on aurait fait un <code>return</code>.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Invariants et terminaison — Q05 : Variant for vs while</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Pour une boucle <code>for i in range(n):</code>, est-il<br/>
nécessaire de prouver la terminaison ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Astuce : si possible, écrire <code>for</code> plutôt que<br/>
<code>while</code> pour éviter de devoir prouver la<br/>
terminaison. C'est aussi plus lisible.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Oui, mais seulement lorsque $n$ est pair</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>La parité de $n$ n'a<br/>
aucun rapport avec la<br/>
terminaison de la<br/>
boucle.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Non, mais il faut prouver l'invariant</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Pertinent pour la <strong>correction</strong> mais hors<br/>
sujet ici (la question portait sur la<br/>
terminaison).</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Non, une boucle <code>for</code> sur un itérateur fini termine automatiquement</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : Python garantit la<br/>
terminaison d'un <code>for</code> sur un <code>range</code> fini<br/>
ou une liste finie. Pas besoin de variant.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Oui, comme pour toute boucle</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Trop strict : la terminaison est<br/>
<strong>automatique</strong> pour une boucle <code>for</code> sur un<br/>
itérateur fini.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Invariants et terminaison — Q06 : Distinction</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Invariant et variant : quelle est la différence<br/>
essentielle ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Mnémonique : « in » comme « <strong>in</strong>variable » →<br/>
reste vrai (correction) ; « variant » comme<br/>
« ça change vers le bas » → décroît strictement<br/>
(terminaison).</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Aucune, ce sont synonymes</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : ce sont deux notions distinctes.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Les deux servent à compter les opérations</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : le compteur d'opérations est lié à la<br/>
complexité, pas à ces notions.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>L'invariant prouve la correction, le variant prouve la terminaison</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : invariant → résultat juste à<br/>
la sortie ; variant → la sortie est<br/>
atteinte.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>L'invariant est de nature mathématique, le variant est de nature physique</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Cette distinction est<br/>
inexacte : ces deux<br/>
notions sont, l'une et<br/>
l'autre, des propriétés<br/>
mathématiques de la<br/>
boucle.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Invariants et terminaison — Q07 : Invariant : somme</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p><pre><code>somme = 0
for x in liste:
    somme += x</code></pre><br/>
Quel est l'invariant après k itérations ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>C'est l'invariant le plus simple à formuler :<br/>
« la variable accumule progressivement ce<br/>
qu'elle doit ». Ce schéma apparaît dans tous<br/>
les calculs incrémentaux.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p><code>somme = 0</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : la somme augmente.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p><code>somme &gt; 0</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : la liste peut contenir des nombres<br/>
négatifs.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p><code>somme = liste[0]</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : seulement après la première<br/>
itération, et pas un invariant général.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p><code>somme = somme des k premiers éléments de liste</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : à l'entrée de l'itération<br/>
k+1, <code>somme</code> contient la somme des k<br/>
éléments déjà parcourus. À la sortie<br/>
(k = n), c'est la somme totale.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Invariants et terminaison — Q08 : Variant simple</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p><pre><code>n = 10
while n &gt; 0:
    n -= 1</code></pre><br/>
Quel est un variant valide ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Variant typique : la quantité contrôlée par la<br/>
condition d'arrêt, qui converge vers la<br/>
condition finale.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="100" format="html">
    <text><![CDATA[<p><code>n</code> lui-même</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : <code>n</code> est un entier ≥ 0 qui<br/>
décroît strictement (<code>n -= 1</code> à chaque<br/>
tour). Quand n atteint 0, on sort.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>La constante 10</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : une constante ne décroît pas.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>La chaîne <code>"hello"</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : un variant doit être une quantité<br/>
entière (ou minorée) qui décroît.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Le booléen <code>n &gt; 0</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : un booléen ne décroît pas (au sens<br/>
numérique).</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Invariants et terminaison — Q09 : Boucle infinie</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p><pre><code>i = 0
while i &lt; 10:
    print(i)</code></pre><br/>
Pourquoi cette boucle ne termine-t-elle pas ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Bug très classique chez les débutants : oublier<br/>
de modifier la variable de boucle. Toujours<br/>
vérifier qu'un variant décroît à chaque tour.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Parce que <code>print</code> est interdit</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : <code>print</code> est valide.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Parce que <code>i</code> n'est jamais modifié : il n'y a pas de variant qui décroît</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : la condition <code>i &lt; 10</code> reste<br/>
toujours vraie. Pas de progression vers la<br/>
terminaison. Solution : ajouter <code>i += 1</code><br/>
dans la boucle.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Parce que 10 n'est pas un entier</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : 10 est bien un entier.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Parce que Python est lent</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : aucune relation avec la performance.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Invariants et terminaison — Q10 : Pourquoi prouver ?</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Pourquoi prouver la correction d'un algorithme<br/>
au lieu de simplement le tester ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Citation célèbre de Dijkstra : « Tester ne peut<br/>
jamais prouver l'absence de bugs ; au mieux,<br/>
cela peut prouver leur présence. »</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Parce que les preuves sont plus rapides à écrire</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>En pratique, c'est souvent l'inverse !</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Parce qu'aucun nombre fini de tests ne couvre tous les cas possibles ; une preuve garantit la correction sur toutes les entrées valides</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : les tests valident sur les<br/>
cas testés ; la preuve garantit l'absence<br/>
de bugs sur toutes les entrées. Pour des<br/>
systèmes critiques (avions, médical),<br/>
c'est essentiel.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Parce que c'est obligatoire en cours</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Argument scolaire, pas scientifique.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Parce que les tests sont chers</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : les tests automatisés sont peu<br/>
coûteux.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Invariants et terminaison — Q11 : Trois étapes de preuve</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Une preuve d'invariant comporte combien<br/>
d'étapes ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>C'est la même structure qu'une preuve par<br/>
<strong>récurrence</strong> : initialisation, hérédité,<br/>
conclusion. L'invariant de boucle est en fait<br/>
une récurrence sur le numéro de l'itération.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Aucune, une preuve d'invariant est implicite</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : il faut bien la justifier.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Trois : initialisation, hérédité (préservation), terminaison</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : (1) <strong>Initialisation</strong> :<br/>
l'invariant est vrai avant la première<br/>
itération ; (2) <strong>Hérédité</strong> : s'il est<br/>
vrai à l'entrée d'un tour, il l'est à la<br/>
sortie ; (3) <strong>Terminaison</strong> : à la sortie<br/>
de la boucle, l'invariant + la condition<br/>
d'arrêt donnent le résultat voulu.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Une seule</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Une étape unique ne<br/>
permet pas d'établir<br/>
la correction d'une<br/>
boucle. Il faut au<br/>
minimum vérifier<br/>
l'initialisation, la<br/>
conservation et l'effet<br/>
obtenu en sortie.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Cinq</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : trois suffisent.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Invariants et terminaison — Q12 : Invariant : minimum</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p><pre><code>m = liste[0]
for x in liste[1:]:
    if x &lt; m:
        m = x</code></pre><br/>
Quel est l'invariant après l'itération sur les<br/>
k premiers éléments ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Schéma « accumulateur » : la variable <code>m</code><br/>
agrège progressivement la propriété (ici, le<br/>
min) sur les éléments parcourus.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p><code>m == liste[0]</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : <code>m</code> peut être mis à jour.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p><code>m == len(liste)</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : pas de relation avec la taille.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p><code>m</code> est le minimum des k premiers éléments parcourus</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : à chaque tour, on met à<br/>
jour <code>m</code> si l'élément courant est plus<br/>
petit. À la fin, c'est le min de toute la<br/>
liste.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p><code>m == 0</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : pas de raison d'être nul.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Invariants et terminaison — Q13 : Variant dichotomie</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Pour la <strong>recherche dichotomique</strong> itérative,<br/>
quel est le variant le plus naturel ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Le variant est ce qui « pousse » l'algorithme<br/>
vers sa fin. Pour la dichotomie, c'est<br/>
l'<strong>intervalle de recherche</strong> qui rétrécit.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Le compteur d'itérations</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Possible, mais on préfère exprimer le<br/>
variant par les variables de l'algorithme.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>La longueur de la liste</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : la longueur de la liste est<br/>
constante.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>La taille de l'intervalle de recherche : <code>d - g + 1</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : à chaque itération,<br/>
l'intervalle est divisé par 2 (donc<br/>
décroît strictement). Quand il atteint 0<br/>
(ou devient négatif), on sort.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>La cible</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : la cible est constante.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Invariants et terminaison — Q14 : Bug par variant</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p><pre><code>def f(n):
    while n != 1:
        if n % 2 == 0:
            n = n // 2
        else:
            n = 3 * n + 1</code></pre><br/>
Cette boucle termine-t-elle pour tout n entier ≥ 1 ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Cas instructif : trouver un variant peut être<br/>
<strong>très difficile</strong>. Pour la suite de Syracuse,<br/>
personne n'a encore réussi.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Non, car n = 5 fait boucler</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : pour n = 5, la suite atteint 1<br/>
rapidement. Aucun contre-exemple connu.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Oui, car n décroît à chaque tour</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : <code>n = 3n + 1</code> <strong>augmente</strong> n. Pas de<br/>
variant évident qui décroît à chaque tour.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Oui, parce que Python le détecterait</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : Python n'a aucun mécanisme de<br/>
détection de boucle infinie.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>La terminaison n'est pas connue : c'est la fameuse conjecture de Syracuse (Collatz), non démontrée</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : c'est l'un des plus<br/>
célèbres problèmes ouverts en mathématiques.<br/>
On a vérifié pour n très grand mais aucune<br/>
preuve générale.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Invariants et terminaison — Q15 : Pré et post-conditions</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Que sont les <strong>préconditions</strong> et<br/>
<strong>postconditions</strong> d'une fonction ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>L'invariant relie pré et postcondition à<br/>
l'intérieur d'une boucle. Ces notions<br/>
structurent la programmation <strong>par contrat</strong>.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>La précondition est ce que la fonction suppose sur ses arguments ; la postcondition est ce qu'elle garantit sur le résultat</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : « si X (précondition) est<br/>
vraie en entrée, alors Y (postcondition)<br/>
est vraie en sortie ». C'est un <strong>contrat</strong>.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Des décorateurs Python</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Possible avec des bibliothèques (par<br/>
exemple <code>icontract</code>), mais ce n'est pas la<br/>
définition.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Le code situé avant et après l'appel à la fonction</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Cette interprétation<br/>
littérale du nom est<br/>
inexacte. Les pré- et<br/>
postconditions sont des<br/>
propriétés logiques sur<br/>
les arguments et le<br/>
résultat, et non des<br/>
fragments de code.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Des commentaires inutiles</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : ce sont des éléments de<br/>
spécification rigoureuse.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Invariants et terminaison — Q16 : Décroissance stricte</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Pourquoi le variant doit-il décroître<br/>
<strong>strictement</strong> (et pas seulement « ne pas<br/>
augmenter ») ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Mathématiquement, une suite d'entiers<br/>
strictement décroissante et minorée par 0 est<br/>
finie (par bonne fondation de ℕ). Cette<br/>
propriété fonde la preuve de terminaison.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Parce que la preuve serait plus longue à rédiger sinon</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>La longueur de la preuve<br/>
n'est pas le motif. La<br/>
décroissance stricte est<br/>
requise pour des raisons<br/>
mathématiques de fond,<br/>
comme expliqué dans la<br/>
bonne réponse.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Parce qu'une suite d'entiers minorée et qui ne décroît pas strictement peut stagner indéfiniment</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : la stagnation = boucle<br/>
infinie. La décroissance stricte garantit<br/>
que l'on s'approche du seuil de sortie à<br/>
chaque tour.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Pour rendre la démonstration plus élégante visuellement</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>La décroissance stricte<br/>
répond à un besoin<br/>
mathématique précis :<br/>
assurer que la boucle<br/>
ne stagne pas et finit<br/>
par s'arrêter.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Parce que Python l'exige</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : Python n'a pas cette contrainte.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Invariants et terminaison — Q17 : Invariant : tri par sélection</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Dans le tri par sélection, après la k-ème<br/>
itération de la boucle externe, quel est<br/>
l'invariant ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Cet invariant rend la correction du tri par<br/>
sélection évidente : à la fin (k = n), les n<br/>
premiers (= toute la liste) sont triés.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Les k premiers éléments sont triés et plus petits que tous les autres</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : c'est l'invariant clé du<br/>
tri par sélection. À l'itération k, on a<br/>
fixé les positions 0..k-1 avec les k plus<br/>
petits éléments dans l'ordre.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>La liste est entièrement triée</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Trop fort : seules les k premières<br/>
positions sont triées.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Les k premiers éléments sont les plus grands</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : le tri par sélection met les plus<br/>
petits en début (tri croissant).</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>La liste est inchangée</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : on a fait des échanges.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Invariants et terminaison — Q18 : Variant multivarié</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Pour la dichotomie itérative, peut-on choisir<br/>
<code>g</code> (l'indice de gauche) seul comme variant ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Astuce : si une variable augmente, prendre son<br/>
complément (par exemple <code>n - i</code>) comme variant.<br/>
Le choix du variant est souvent affaire de<br/>
reformulation.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Oui, parfait</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : <code>g</code> peut rester constant si c'est<br/>
<code>d</code> qui change.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Non, parce que <code>g</code> n'est pas un entier</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : <code>g</code> est bien un entier.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Non, parce que <code>g</code> ne décroît pas (il augmente ou reste constant)</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : on cherche une quantité<br/>
qui décroît. Avec <code>g</code> qui augmente, il<br/>
faut prendre par exemple <code>n - g</code> ou bien<br/>
la taille de l'intervalle <code>d - g</code>.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Oui, mais seulement si la liste est triée</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : la précondition de tri n'a aucun<br/>
rôle dans la <strong>terminaison</strong>.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Invariants et terminaison — Q19 : Bonne formulation</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Pour qu'un invariant soit utile à la preuve,<br/>
il faut qu'il soit :</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Trop faible : ne dit rien d'utile. Trop fort :<br/>
faux. Le bon niveau est celui qui, combiné à la<br/>
condition d'arrêt, donne exactement la<br/>
postcondition.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Long et compliqué</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Au contraire, on cherche le plus simple<br/>
possible.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Toujours faux</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Absurde : un invariant doit être <strong>vrai</strong>.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Codé dans Python</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Sans rapport : un invariant est une<br/>
propriété mathématique.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Vrai à l'initialisation et suffisamment fort pour impliquer la postcondition au moment de la sortie</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : un invariant trop faible<br/>
ne donne rien à la sortie ; un invariant<br/>
trop fort peut être faux. Trouver le bon<br/>
niveau est tout l'art.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Invariants et terminaison — Q20 : Outils</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Quel outil aide à <strong>détecter</strong> un bug dans un<br/>
invariant ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Les <code>assert</code> sont une excellente pratique :<br/>
ils transforment des invariants implicites en<br/>
vérifications explicites, attrapant les bugs<br/>
au plus tôt.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Un débogueur visuel</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Possible mais vague. Quelque chose de plus<br/>
précis est demandé.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Un commentaire <code># TODO</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : un commentaire ne vérifie rien.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Un <code>assert</code> placé dans la boucle pour vérifier l'invariant à l'exécution</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : par exemple<br/>
<code>assert m == min(liste[:i+1])</code>. Si<br/>
l'invariant échoue à un tour, Python lève<br/>
<code>AssertionError</code> et indique le bug.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>La fonction <code>print()</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Possible mais moins systématique qu'un<br/>
<code>assert</code>.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Invariants et terminaison — Q21 : Invariant insuffisant</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Pour le tri par sélection, l'invariant<br/>
« les k premiers éléments sont triés » est-il<br/>
suffisant ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Bon invariant pour la sélection :<br/>
<code>liste[0..k-1]</code> (en Python : <code>liste[:k]</code>) est<br/>
trié <strong>et</strong> ne contient que des éléments<br/>
plus petits que tout ceux de <code>liste[k..n-1]</code><br/>
(en Python : <code>liste[k:]</code>). Les deux<br/>
conditions sont nécessaires.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Oui, à condition d'utiliser un tri stable</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : la stabilité n'a aucun rôle ici.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Oui, à condition que la liste soit triée à l'avance</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : on n'a pas cette précondition.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Oui, c'est suffisant</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Insuffisant : « les k premiers triés » ne<br/>
dit pas qu'ils sont les plus petits. Si le<br/>
maximum se retrouvait en <code>liste[0]</code> et le<br/>
minimum en <code>liste[1]</code>, ce serait « trié »<br/>
(ordre 1 puis 2 éléments), mais incorrect.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Non, il manque la condition que ces éléments soient plus petits que ceux de <code>liste[k..n-1]</code> (en Python : <code>liste[k:]</code>)</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : sans cette condition<br/>
supplémentaire, l'algorithme pourrait<br/>
terminer avec <code>liste[0..k-1]</code> (en Python :<br/>
<code>liste[:k]</code>) triés mais contenant des<br/>
« gros » éléments, et le résultat final<br/>
serait faux.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Invariants et terminaison — Q22 : Trouver le variant</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p><pre><code>while a &gt; b:
    a = a - b</code></pre><br/>
(avec <code>a, b</code> entiers, <code>b &gt; 0</code>). Quel est un<br/>
variant valide ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Cette boucle calcule <code>a mod b</code> (reste de la<br/>
division euclidienne). C'est un cas classique<br/>
illustrant variant et terminaison.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="100" format="html">
    <text><![CDATA[<p><code>a</code> (qui décroît strictement à chaque tour, et est minoré par <code>b</code> à la sortie)</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : à chaque tour <code>a -= b</code><br/>
avec <code>b &gt; 0</code> donc <code>a</code> décroît<br/>
strictement. La boucle se termine quand<br/>
<code>a &lt;= b</code>.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>La constante 1</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : une constante ne décroît pas.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p><code>b</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : <code>b</code> ne change pas dans la boucle.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p><code>a - b</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Possible, mais à chaque tour <code>a - b</code><br/>
change : à voir si décroissance stricte.<br/>
On peut faire mieux et plus simple.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Invariants et terminaison — Q23 : Preuve par récurrence</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Pourquoi la preuve d'un invariant fait-elle<br/>
penser à une <strong>preuve par récurrence</strong> ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>C'est le pont entre <strong>mathématiques</strong> et<br/>
<strong>informatique</strong> : la preuve algorithmique<br/>
utilise les outils du raisonnement<br/>
mathématique. L'invariant est une propriété<br/>
<code>P(k)</code> à prouver par récurrence sur k.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Parce que les deux utilisent des indices</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Vague et superficiel.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Aucun rapport entre les deux</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : la similarité est profonde.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Parce qu'on prouve l'invariant à la 1ʳᵉ itération (initialisation), puis qu'on prouve qu'il est conservé d'une itération à la suivante (hérédité), exactement comme une récurrence sur le numéro d'itération</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : invariant de boucle =<br/>
récurrence sur le compteur d'itérations.<br/>
C'est la même structure logique.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Parce que c'est imposé par les règles du langage</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Aucun langage de<br/>
programmation n'impose<br/>
de prouver les<br/>
invariants par<br/>
récurrence. C'est une<br/>
démarche<br/>
mathématique, qui<br/>
relève du raisonnement,<br/>
pas du langage.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Invariants et terminaison — Q24 : Inventer l'invariant</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p><pre><code>r = 0
n = N
while n &gt; 0:
    n = n // 2
    r = r + 1</code></pre><br/>
Que calcule cette boucle, et quel invariant<br/>
rend ce calcul évident ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Cet algorithme calcule le <strong>logarithme entier</strong>.<br/>
C'est aussi la base de la complexité O(log n)<br/>
de la dichotomie : on divise par 2 jusqu'à<br/>
atteindre 0.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>La boucle compte de 1 à N</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : <code>n</code> est divisé par 2, pas<br/>
décrémenté.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p><code>r</code> est toujours 0</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : <code>r</code> est incrémenté.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p><code>r</code> compte le nombre d'itérations ; à la fin, <code>r</code> ≈ ⌊log₂(N)⌋ + 1. Invariant : <code>2^r * n ≥ N</code> (avant l'itération courante).</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : on divise par 2 jusqu'à<br/>
atteindre 0, en comptant. C'est le calcul<br/>
du logarithme entier en base 2. Le<br/>
variant : <code>n</code> (qui décroît<br/>
strictement par division entière).</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>La boucle ne termine pas</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : <code>n // 2</code> ramène n à 0 en log₂(N)<br/>
étapes.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Invariants et terminaison — Q25 : Synthèse</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Parmi les affirmations suivantes sur les<br/>
invariants et la terminaison, laquelle est<br/>
<strong>fausse</strong> ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Distinction terminologique : <strong>correction<br/>
partielle</strong> = « si termine, alors juste » ;<br/>
<strong>correction totale</strong> = correction partielle +<br/>
terminaison. C'est la correction totale qu'on<br/>
veut habituellement.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Un programme correct est nécessairement un programme qui termine</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Faux (donc bonne réponse) : la correction<br/>
est une propriété <strong>conditionnelle</strong> :<br/>
« si le programme termine, le résultat<br/>
est juste ». La terminaison est une<br/>
propriété <strong>distincte</strong>. Un programme<br/>
peut être correct mais ne pas terminer<br/>
(par exemple s'il calcule une fonction<br/>
partielle).</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Un variant doit être un entier (ou une quantité minorée) qui décroît strictement</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Vrai : sinon la décroissance peut être<br/>
infinie.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Un invariant doit être vrai à chaque entrée d'itération</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Vrai : c'est sa définition.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Toute boucle <code>for i in range(n)</code> se termine, sans qu'on ait besoin de prouver de variant</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Vrai : la boucle <code>for</code> sur un itérateur<br/>
fini termine automatiquement.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Invariants et terminaison — Q26 : Invariant : tri par insertion</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Dans le tri par insertion, après l'itération<br/>
<code>i</code> de la boucle externe, quel invariant<br/>
caractérise correctement l'état de la liste ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Différence clé avec le tri par sélection :<br/>
l'invariant de l'insertion porte sur le tri<br/>
d'une partie initiale (sans hypothèse sur les<br/>
valeurs), alors que celui de la sélection<br/>
ajoute la condition « plus petits que les<br/>
autres ».</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>La sous-liste <code>liste[0..i]</code> (en Python : <code>liste[:i+1]</code>) contient les mêmes éléments qu'au début, mais elle est triée</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : c'est l'invariant clé du<br/>
tri par insertion. Les <code>i + 1</code> premiers<br/>
éléments restent les mêmes (à l'ensemble<br/>
près) qu'avant la boucle, mais maintenant<br/>
ordonnés. À la dernière itération<br/>
<code>i = n - 1</code>, toute la liste est triée.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>La liste est entièrement triée</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : trop fort. À l'itération <code>i</code>,<br/>
seuls les <code>i + 1</code> premiers éléments sont<br/>
triés ; les éléments suivants n'ont pas<br/>
encore été traités.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Les <code>i</code> premiers éléments sont les plus grands</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : ce serait un tri décroissant ou<br/>
un tri par sélection inversé. Le tri par<br/>
insertion classique est croissant et ne<br/>
place pas les plus grands en tête.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Les <code>i</code> premiers éléments sont triés et plus petits que tous les autres</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : c'est l'invariant du tri par<br/>
<strong>sélection</strong>. Le tri par insertion ne<br/>
place pas les plus petits en tête à chaque<br/>
étape ; il insère le <code>i</code>-ème élément à sa<br/>
place dans la partie déjà traitée.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Invariants et terminaison — Q27 : Terminaison de l'algorithme d'Euclide</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>L'algorithme d'Euclide pour le PGCD s'écrit :<br/>
<pre><code>def pgcd(a, b):
    while b != 0:
        a, b = b, a % b
    return a</code></pre><br/>
(avec <code>a, b</code> entiers naturels, <code>b &gt; 0</code> à<br/>
l'entrée). Quel est un variant qui prouve la<br/>
terminaison ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Une remarque profonde : ici, l'<strong>invariant</strong><br/>
est <code>pgcd(a, b) = pgcd(a₀, b₀)</code> (la valeur<br/>
initiale du PGCD est conservée), tandis que le<br/>
<strong>variant</strong> est <code>b</code>. À la sortie, l'invariant<br/>
donne <code>pgcd(a, 0) = a₀ ∗</code>, ce qui est bien le<br/>
PGCD recherché.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>La valeur de <code>b</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : à chaque itération, <code>b</code><br/>
devient <code>a % b</code>, qui est strictement<br/>
inférieur à l'ancien <code>b</code>. Comme <code>b</code> est un<br/>
entier naturel minoré par <code>0</code>, la suite des<br/>
valeurs de <code>b</code> est strictement décroissante<br/>
et finie. La boucle se termine donc.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Le PGCD lui-même</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : l'invariant de l'algorithme est<br/>
précisément que <code>pgcd(a, b)</code> reste<br/>
constant à chaque itération. Une quantité<br/>
constante ne peut servir de variant (qui<br/>
doit décroître strictement).</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>La somme <code>a + b</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : la somme peut augmenter ou<br/>
stagner selon les cas. Par exemple<br/>
<code>pgcd(5, 12)</code> : avant, <code>a + b = 17</code> ;<br/>
après, <code>a + b = 12 + 5 = 17</code>. Donc pas de<br/>
décroissance stricte.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>La valeur de <code>a</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : <code>a</code> ne décroît pas forcément à<br/>
chaque tour. Par exemple avec <code>a = 5</code>,<br/>
<code>b = 12</code>, après une itération on a<br/>
<code>a = 12, b = 5</code>, donc <code>a</code> a augmenté.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Invariants et terminaison — Q28 : Assertion d'invariant en pratique</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>On suspecte qu'une boucle calcule mal une<br/>
somme. Quel ajout permet de <strong>détecter<br/>
automatiquement</strong> une violation d'invariant<br/>
pendant l'exécution ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Bonne pratique : exprimer les invariants<br/>
critiques sous forme d'assertions pendant la<br/>
phase de développement. Cela transforme les<br/>
bugs silencieux en erreurs immédiates et<br/>
réduit considérablement le temps de<br/>
débogage.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Un commentaire <code># vérification de l'invariant</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : un commentaire est inerte. Il<br/>
n'est lu que par le programmeur, pas par<br/>
l'interpréteur Python. Aucun bug ne peut<br/>
être détecté ainsi.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Une instruction <code>assert</code> exprimant l'invariant attendu, par exemple <code>assert somme == sum(liste[:i+1])</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : <code>assert</code> lève<br/>
immédiatement une <code>AssertionError</code> si la<br/>
condition est fausse, ce qui localise<br/>
précisément l'itération où l'invariant a<br/>
été rompu. C'est un outil de débogage très<br/>
efficace, à retirer ou à désactiver<br/>
(<code>python -O</code>) en production.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Une exception <code>try/except</code> autour de la boucle</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : un <code>try/except</code> capture les<br/>
erreurs <strong>levées par Python</strong>, pas les<br/>
violations d'invariant logique. Si la<br/>
boucle calcule une mauvaise somme sans<br/>
erreur d'exécution, le <code>try/except</code> ne<br/>
détectera rien.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Un appel à <code>print</code> affichant la valeur courante de la variable</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Possible mais limité : il faut alors<br/>
inspecter la sortie à l'œil nu et<br/>
identifier visuellement une anomalie. Pas<br/>
de détection automatique.</p>]]></text>
    </feedback>
  </answer>
</question>

</quiz>
