<?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 fin</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 while,<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> d - g qui décroît<br/>
strictement. Pour while x &gt; 0: x -= 1, c'est<br/>
x 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 for i in<br/>
range(len(liste)), quel est l'<strong>invariant</strong> à<br/>
l'entrée du tour i ?</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 liste[0..i-1] (notation algorithmique pour les éléments déjà parcourus ; en Python : liste[:i])</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : à l'entrée de l'itération<br/>
i, 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 return.</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 for i in range(n):, est-il<br/>
nécessaire de prouver la terminaison ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Astuce : si possible, écrire for plutôt que<br/>
while 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 for 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 for sur un range 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 for 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>`<code>python<br/>
somme = 0<br/>
for x in liste:<br/>
    somme += x<br/>
</code>`<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>somme = 0</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : la somme augmente.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>somme &gt; 0</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>somme = liste[0]</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>somme = somme des k premiers éléments de liste</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : à l'entrée de l'itération<br/>
k+1, somme 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>`<code>python<br/>
n = 10<br/>
while n &gt; 0:<br/>
    n -= 1<br/>
</code>`<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>n lui-même</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : n est un entier ≥ 0 qui<br/>
décroît strictement (n -= 1 à 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 "hello"</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 n &gt; 0</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>`<code>python<br/>
i = 0<br/>
while i &lt; 10:<br/>
    print(i)<br/>
</code>`<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 print est interdit</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : print est valide.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Parce que i 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 i &lt; 10 reste<br/>
toujours vraie. Pas de progression vers la<br/>
terminaison. Solution : ajouter i += 1<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>`<code>python<br/>
m = liste[0]<br/>
for x in liste[1:]:<br/>
    if x &lt; m:<br/>
        m = x<br/>
</code>`<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 m<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>m == liste[0]</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : m peut être mis à jour.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>m == len(liste)</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>m 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 m 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>m == 0</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 : d - g + 1</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>`<code>python<br/>
def f(n):<br/>
    while n != 1:<br/>
        if n % 2 == 0:<br/>
            n = n // 2<br/>
        else:<br/>
            n = 3 * n + 1<br/>
</code>`<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 : n = 3n + 1 <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 icontract), 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/>
g (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 n - i) 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 : g peut rester constant si c'est<br/>
d qui change.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Non, parce que g n'est pas un entier</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : g est bien un entier.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Non, parce que g 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 g qui augmente, il<br/>
faut prendre par exemple n - g ou bien<br/>
la taille de l'intervalle d - g.</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 assert 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 # TODO</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 assert 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/>
assert m == min(liste[:i+1]). Si<br/>
l'invariant échoue à un tour, Python lève<br/>
AssertionError et indique le bug.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>La fonction print()</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Possible mais moins systématique qu'un<br/>
assert.</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/>
liste[0..k-1] (en Python : liste[:k]) est<br/>
trié <strong>et</strong> ne contient que des éléments<br/>
plus petits que tout ceux de liste[k..n-1]<br/>
(en Python : liste[k:]). 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 liste[0] et le<br/>
minimum en liste[1], 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 liste[k..n-1] (en Python : liste[k:])</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : sans cette condition<br/>
supplémentaire, l'algorithme pourrait<br/>
terminer avec liste[0..k-1] (en Python :<br/>
liste[:k]) 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>`<code>python<br/>
while a &gt; b:<br/>
    a = a - b<br/>
</code><br/>
(avec a, b entiers, b &gt; 0`). Quel est un<br/>
variant valide ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Cette boucle calcule a mod b (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>a (qui décroît strictement à chaque tour, et est minoré par b à la sortie)</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : à chaque tour a -= b<br/>
avec b &gt; 0 donc a décroît<br/>
strictement. La boucle se termine quand<br/>
a &lt;= b.</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>b</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : b ne change pas dans la boucle.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>a - b</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Possible, mais à chaque tour a - b<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/>
P(k) à 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>`<code>python<br/>
r = 0<br/>
n = N<br/>
while n &gt; 0:<br/>
    n = n // 2<br/>
    r = r + 1<br/>
</code>`<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 : n est divisé par 2, pas<br/>
décrémenté.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>r est toujours 0</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : r est incrémenté.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>r compte le nombre d'itérations ; à la fin, r ≈ ⌊log₂(N)⌋ + 1. Invariant : 2^r * n ≥ N (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 : n (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 : n // 2 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 for i in range(n) se termine, sans qu'on ait besoin de prouver de variant</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Vrai : la boucle for 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/>
i 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 liste[0..i] (en Python : liste[:i+1]) 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 i + 1 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/>
i = n - 1, 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 i,<br/>
seuls les i + 1 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 i 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 i 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 i-è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/>
`<code>python<br/>
def pgcd(a, b):<br/>
    while b != 0:<br/>
        a, b = b, a % b<br/>
    return a<br/>
</code><br/>
(avec a, b entiers naturels, b &gt; 0` à<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 pgcd(a, b) = pgcd(a₀, b₀) (la valeur<br/>
initiale du PGCD est conservée), tandis que le<br/>
<strong>variant</strong> est b. À la sortie, l'invariant<br/>
donne pgcd(a, 0) = a₀ ∗, 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 b</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : à chaque itération, b<br/>
devient a % b, qui est strictement<br/>
inférieur à l'ancien b. Comme b est un<br/>
entier naturel minoré par 0, la suite des<br/>
valeurs de b 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 pgcd(a, b) 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 a + b</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : la somme peut augmenter ou<br/>
stagner selon les cas. Par exemple<br/>
pgcd(5, 12) : avant, a + b = 17 ;<br/>
après, a + b = 12 + 5 = 17. Donc pas de<br/>
décroissance stricte.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>La valeur de a</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : a ne décroît pas forcément à<br/>
chaque tour. Par exemple avec a = 5,<br/>
b = 12, après une itération on a<br/>
a = 12, b = 5, donc a 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 # vérification de l'invariant</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 assert exprimant l'invariant attendu, par exemple assert somme == sum(liste[:i+1])</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : assert lève<br/>
immédiatement une AssertionError 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/>
(python -O) en production.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Une exception try/except autour de la boucle</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : un try/except 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 try/except ne<br/>
détectera rien.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Un appel à print 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>
