<?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é conservée à chaque itération</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 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>La présence d'une condition d'arrêt dans la boucle</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : la présence d'une<br/>
condition d'arrêt ne suffit<br/>
pas. Si elle ne devient<br/>
jamais fausse, la boucle est<br/>
infinie : la terminaison est<br/>
la propriété que l'algorithme<br/>
s'arrête réellement.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Le fait que l'algorithme renvoie un résultat correct</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : c'est la <strong>correction</strong>.<br/>
Un algorithme peut être correct<br/>
(bon résultat s'il s'arrête) sans<br/>
terminer ; les deux propriétés se<br/>
prouvent séparément.</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>L'algorithme s'arrête en un nombre fini d'étapes</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>Un entier minoré qui décroît strictement</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é 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 déjà 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'est pas dans <code>liste[:i]</code> (déjà parcourus)</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 un nombre 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, un <code>for</code> sur un itérateur fini termine seul</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</code> garde la valeur 0 tant que la boucle tourne</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : <code>somme</code> est modifiée à chaque tour<br/>
par <code>somme += x</code> ; elle ne reste nulle que si<br/>
tous les éléments parcourus sont nuls.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p><code>somme</code> est strictement positive à chaque itération</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : la liste peut contenir des nombres<br/>
négatifs ou nuls, et <code>somme</code> peut donc être<br/>
négative ou nulle à tout moment.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p><code>somme</code> vaut le premier élément <code>liste[0]</code> de la liste</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : c'est vrai seulement après la<br/>
première itération. Un invariant doit être<br/>
vrai après <strong>chaque</strong> itération.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p><code>somme</code> vaut la somme des k premiers éléments</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 quantité <code>10 - n</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : <code>10 - n</code> <strong>croît</strong> de 0 à 10 au<br/>
fil des tours. Un variant doit être un<br/>
entier positif ou nul qui décroît<br/>
strictement.</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 la condition devrait être <code>i &lt;= 10</code> et non <code>i &lt; 10</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : la borne n'est pas en cause. Avec<br/>
<code>i &lt;= 10</code>, la boucle ne terminerait pas<br/>
davantage, car <code>i</code> ne change jamais.</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 <code>print(i)</code> modifie la valeur de <code>i</code> à chaque tour</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : <code>print</code> se contente d'afficher son<br/>
argument, il ne le modifie pas. C'est<br/>
justement parce que rien ne modifie <code>i</code> que<br/>
la condition reste vraie.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Parce que la condition <code>i &lt; 10</code> n'est testée qu'une seule fois, au départ</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : la condition d'un <code>while</code> est<br/>
réévaluée avant chaque tour. Ici elle est<br/>
bien retestée, mais reste vraie à chaque<br/>
fois parce que <code>i</code> vaut toujours 0.</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>Aucun test fini ne couvre tous les cas, une preuve oui</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, la preuve d'invariant est totalement 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é, 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</code> vaut toujours le premier élément <code>liste[0]</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : <code>m</code> est mis à jour dès qu'un<br/>
élément plus petit que lui est rencontré.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p><code>m</code> vaut le dernier élément examiné par la boucle</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : <code>m</code> ne prend la valeur de l'élément<br/>
courant que s'il est plus petit ; sinon il<br/>
garde sa valeur.</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</code> vaut le minimum de la liste entière dès le premier tour</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : confusion entre invariant et<br/>
<strong>postcondition</strong>. Le minimum global n'est<br/>
garanti qu'à la sortie de la boucle, pas<br/>
pendant son exécution.</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 courant</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : un compteur <strong>croît</strong> à chaque tour,<br/>
alors qu'un variant doit décroître strictement<br/>
vers 0. On exprime le variant avec les<br/>
variables de l'algorithme.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>La longueur totale de la liste parcourue</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : la longueur de la liste ne change pas<br/>
d'une itération à l'autre ; une quantité<br/>
constante ne peut pas servir de variant.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>La taille <code>d - g + 1</code> de l'intervalle</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 valeur de la cible recherchée</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : la cible ne change pas pendant la<br/>
recherche, elle ne peut donc pas décroître.</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 : pour n = 5, la suite boucle sans atteindre 1</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : pour n = 5, la suite atteint 1<br/>
rapidement (5, 16, 8, 4, 2, 1). Aucun<br/>
contre-exemple n'est connu.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Oui : n décroît à chaque tour jusqu'à atteindre 1</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : <code>n = 3n + 1</code> <strong>augmente</strong> n. Il n'y<br/>
a pas de variant évident qui décroît à<br/>
chaque tour.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Oui : Python détecte et interrompt les boucles infinies</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : Python n'a aucun mécanisme de<br/>
détection de boucle infinie (un tel<br/>
détecteur général est d'ailleurs impossible).</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>On ne sait pas : la terminaison pour tout n est un problème ouvert</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : c'est la fameuse conjecture<br/>
de Syracuse (ou de Collatz), 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 n'existe.</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>Hypothèse sur les arguments, garantie 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é juste avant et juste 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>Une suite minorée non strictement décroissante peut stagner</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 : compteur d'occurrences</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p><pre><code>c = 0
for i in range(len(liste)):
    if liste[i] == cible:
        c = c + 1</code></pre><br/>
Quel invariant est vérifié à l'entrée du tour<br/>
<code>i</code>, avant le test <code>liste[i] == cible</code> ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Un compteur suit le même schéma qu'une somme :<br/>
l'invariant décrit ce que <code>c</code> représente pour<br/>
la partie déjà parcourue, <code>liste[:i]</code>. À la<br/>
sortie (<code>i = len(liste)</code>), il donne la<br/>
postcondition : <code>c</code> est le nombre d'occurrences<br/>
dans toute la liste.</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>c</code> est le nombre d'occurrences de <code>cible</code> dans <code>liste[:i]</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : avant le tour <code>i</code>, seuls les<br/>
<code>i</code> premiers éléments ont été examinés, et<br/>
<code>c</code> a été incrémenté une fois par occurrence<br/>
rencontrée. Sur <code>liste = [3, 7, 3, 3]</code> et<br/>
<code>cible = 3</code>, <code>c</code> vaut 0, 1, 1, 2 à l'entrée<br/>
des tours 0, 1, 2, 3, puis 3 à la sortie.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p><code>c</code> est le nombre d'occurrences de <code>cible</code> dans toute la liste</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : c'est la postcondition, vraie<br/>
seulement à la sortie de la boucle. À<br/>
l'entrée du tour 0, <code>c</code> vaut 0 alors que<br/>
<code>[3, 7, 3, 3]</code> contient trois fois la<br/>
cible 3.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p><code>c</code> vaut <code>i</code>, le nombre de tours déjà effectués</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : <code>c</code> ne compte que les tours où le<br/>
test a réussi. Sur <code>[3, 7, 3, 3]</code> avec<br/>
<code>cible = 3</code>, à l'entrée du tour 2 on a<br/>
<code>i = 2</code> mais <code>c = 1</code>.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p><code>c</code> est le nombre d'éléments de <code>liste[:i]</code> différents de <code>cible</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : c'est le complémentaire de ce que<br/>
compte la boucle. À l'entrée du tour 1 sur<br/>
<code>[3, 7, 3, 3]</code> avec <code>cible = 3</code>, <code>c</code> vaut 1<br/>
alors qu'aucun élément déjà vu n'est<br/>
différent de 3.</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 vraiment 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, <code>g</code> ne décroît pas (il augmente)</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, lourd et particulièrement 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 au départ et assez fort en 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 compteur du nombre de tours de la boucle</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : compter les tours renseigne sur la<br/>
terminaison (la boucle s'arrête-t-elle ?),<br/>
pas sur la correction. Une boucle peut faire<br/>
exactement le bon nombre de tours en<br/>
calculant un résultat faux.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Un commentaire <code># TODO</code> placé dans la boucle</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : un commentaire n'est pas exécuté et<br/>
ne vérifie rien.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Un <code>assert</code> de l'invariant dans la boucle</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>Un <code>print()</code> qui signale automatiquement l'invariant faux</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : <code>print</code> affiche une valeur sans la<br/>
comparer à rien. C'est à l'humain de repérer<br/>
l'anomalie dans le flot d'affichages, et rien<br/>
n'arrête le programme.</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 qu'ils soient les plus petits</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>La variable <code>a</code></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 strictement,<br/>
tout en restant strictement positif tant<br/>
que la boucle tourne (<code>a &gt; b &gt; 0</code>). La<br/>
boucle se termine quand <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>La variable <code>b</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : <code>b</code> ne change pas dans la boucle,<br/>
ce n'est donc pas une quantité décroissante.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>La quantité <code>b - a</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : tant que la boucle tourne, <code>a &gt; b</code><br/>
donc <code>b - a</code> est strictement <strong>négatif</strong>, et<br/>
il <strong>croît</strong> à chaque tour. Un variant doit<br/>
être positif ou nul et décroître strictement.</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 simplement 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>On prouve l'initialisation puis l'hérédité, comme une récurrence</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 simplement de 1 jusqu'à 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> reste égal à 0 pendant toute la boucle</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : <code>r = r + 1</code> l'incrémente à chaque<br/>
tour.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Invariant <code>n == N // 2^r</code> ; <code>r</code> compte les tours</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 jamais, <code>n</code> ne devenant jamais nul</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : <code>n // 2</code> ramène n à 0 en log₂(N)<br/>
étapes (par exemple 8, 4, 2, 1, 0).</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 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><code>liste[:i+1]</code> contient les mêmes éléments, mais triés</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 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</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>Un <code>assert</code> vérifiant que le variant décroît à chaque tour</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : ce contrôle porte sur la<br/>
terminaison, pas sur la correction. Le<br/>
variant peut décroître parfaitement pendant<br/>
que la somme se calcule mal : une assertion<br/>
sur le variant ne détecte aucune violation<br/>
d'invariant.</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>
