<?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 ne se trouve à aucun indice situé avant <code>i</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : à l'entrée de l'itération<br/>
<code>i</code>, on a déjà testé les indices 0 à i-1 et<br/>
aucun n'a satisfait le critère. Si on en<br/>
avait trouvé un, on aurait fait un <code>return</code>.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Invariants et terminaison — Q05 : Variant for vs while</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Pour une boucle <code>for i in range(n):</code>, est-il<br/>
nécessaire de prouver la terminaison ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Astuce : si possible, écrire <code>for</code> plutôt que<br/>
<code>while</code> pour éviter de devoir prouver la<br/>
terminaison. C'est aussi plus lisible.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Oui, mais seulement lorsque $n$ est 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 <code>range</code> 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/>
<code>range</code> ou une liste.</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>Trois temps à retenir : l'invariant est vrai<br/>
au départ, chaque tour le conserve, et à la<br/>
sortie il donne, avec la condition d'arrêt,<br/>
le résultat voulu.</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 i in range(1, len(liste)):
    if liste[i] &lt; m:
        m = liste[i]</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 : La boucle de Syracuse</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>La suite de Syracuse part d'un entier $n \geq 1$ : si $n$ est pair, on le<br/>
divise par $2$, sinon on le remplace par $3n + 1$. La <strong>conjecture de<br/>
Syracuse</strong> affirme que cette suite finit toujours par atteindre $1$,<br/>
quel que soit l'entier de départ. Elle a été vérifiée par ordinateur<br/>
pour d'immenses valeurs de $n$, mais personne ne l'a démontrée.</p>
<pre><code>def f(n):
    while n != 1:
        if n % 2 == 0:
            n = n // 2
        else:
            n = 3 * n + 1</code></pre>
<p>Que peut-on affirmer sur la terminaison de cette boucle pour tout<br/>
entier $n \geq 1$ ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Pour prouver qu'une boucle termine, on cherche un variant : une quantité<br/>
entière positive qui décroît strictement à chaque tour. Ici, $n$ monte<br/>
et descend, et personne n'a trouvé de variant : la terminaison de cette<br/>
boucle très simple reste une question ouverte.</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>On ne sait pas : il faudrait pour cela démontrer la conjecture</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : la boucle s'arrête exactement quand la suite atteint $1$.<br/>
Prouver qu'elle termine pour tout $n$ revient donc à démontrer la<br/>
conjecture, ce que personne n'a encore réussi.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Elle termine pour tout $n$, puisque la conjecture a été vérifiée par ordinateur</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : une vérification, même sur d'immenses valeurs, ne couvre pas<br/>
tous les entiers. Seule une démonstration permettrait d'affirmer que la<br/>
boucle termine pour tout $n$.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Elle ne termine pas pour tout $n$, puisque <code>3 * n + 1</code> fait augmenter $n$</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : $n$ augmente parfois, mais cela ne prouve pas que la boucle<br/>
tourne sans fin. Pour $n = 3$, la suite vaut $10$, $5$, $16$, $8$, $4$,<br/>
$2$, $1$ : elle monte puis redescend jusqu'à $1$.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Elle termine pour tout $n$, car un tour sur deux au moins divise $n$ par $2$</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : après <code>3 * n + 1</code>, le nombre obtenu est pair et le tour suivant<br/>
le divise par $2$, mais le résultat $(3n + 1)/2$ reste plus grand que<br/>
$n$. Cette remarque ne fournit donc aucun variant.</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. En Python, des<br/>
assertions (<code>assert</code>) peuvent vérifier ces<br/>
conditions pendant l'exécution.</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 tests écrits après coup pour chercher les bugs</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : tu confonds spécification et jeu de<br/>
tests. Les tests vérifient le programme sur<br/>
quelques exemples ; les préconditions et<br/>
postconditions énoncent ce qui doit être vrai<br/>
pour tous les appels.</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>Une suite d'entiers strictement décroissante<br/>
et minorée par 0 ne peut prendre qu'un nombre<br/>
fini de valeurs. Cette propriété fonde la<br/>
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 n'est pas le motif :<br/>
sans décroissance stricte, le variant peut<br/>
stagner et la boucle ne jamais s'arrêter.</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 : un variant qui stagne<br/>
autorise une boucle infinie. La décroissance<br/>
stricte garantit que l'on s'approche du<br/>
seuil de sortie à 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, les éléments situés<br/>
avant l'indice <code>i</code>. À la sortie<br/>
(<code>i = len(liste)</code>), il donne la postcondition :<br/>
<code>c</code> est le nombre d'occurrences dans toute la<br/>
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> avant l'indice <code>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 différents de <code>cible</code> avant l'indice <code>i</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 : les k<br/>
premiers éléments sont triés <strong>et</strong> chacun<br/>
d'eux est inférieur ou égal à tous les<br/>
éléments d'indice k à n - 1. 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 que la liste ne contienne aucun doublon</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : les doublons ne gênent ni le tri<br/>
par sélection ni sa preuve ; ce qui manque,<br/>
c'est que les k premiers éléments soient les<br/>
plus petits de la liste.</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, on ne peut pas prouver que<br/>
l'invariant se conserve : les k premiers<br/>
éléments pourraient être triés tout en<br/>
contenant de « gros » éléments, et le<br/>
résultat final 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 : Vérifier une postcondition par assertion</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>La fonction suivante doit renvoyer l'indice d'un<br/>
plus petit élément d'une liste non vide <code>t</code> :</p>
<pre><code>def indice_min(t):
    assert len(t) &gt; 0
    k = 0
    for i in range(1, len(t)):
        if t[i] &lt; t[k]:
            k = i
    return k</code></pre>
<p>On veut vérifier, juste avant <code>return k</code>, la<br/>
postcondition « <code>t[k]</code> est inférieur ou égal à<br/>
chacun des éléments de <code>t</code> ». Quelles lignes<br/>
conviennent ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Des assertions garantissent des préconditions,<br/>
comme <code>assert len(t) &gt; 0</code> en début de fonction,<br/>
et des postconditions, vérifiées juste avant de<br/>
renvoyer le résultat. Une postcondition qui<br/>
porte sur tous les éléments se vérifie par une<br/>
boucle d'assertions.</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[<pre><code>for j in range(len(t)):
    assert t[k] &lt; t[j]</code></pre>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : pour <code>j</code> égal à <code>k</code>, <code>t[k] &lt; t[k]</code><br/>
est faux, donc l'assertion échoue à chaque<br/>
appel, même quand la fonction est juste. Il<br/>
faut une inégalité large.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<pre><code>assert t[k] &lt;= t[i]</code></pre>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : après la boucle, <code>i</code> vaut le<br/>
dernier indice parcouru, donc on ne compare<br/>
<code>t[k]</code> qu'au dernier élément. Pour une liste<br/>
d'un seul élément, <code>i</code> n'est même pas défini<br/>
et cette ligne provoque une erreur.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<pre><code>for j in range(len(t)):
    assert t[k] &lt;= t[j]</code></pre>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : la boucle compare <code>t[k]</code> à<br/>
tous les éléments, et l'assertion échoue dès<br/>
que l'un d'eux est strictement plus petit.<br/>
L'inégalité large accepte le cas où <code>j</code> vaut<br/>
<code>k</code>, ainsi que les minimums en double.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<pre><code>assert 0 &lt;= k and k &lt; len(t)</code></pre>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : cette assertion vérifie seulement<br/>
que <code>k</code> est un indice valide. Elle resterait<br/>
vraie si la fonction renvoyait l'indice du<br/>
plus grand élément.</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>On prouve donc deux choses séparément : la<br/>
correction, à l'aide d'un invariant, et la<br/>
terminaison, à l'aide d'un variant. Il faut<br/>
les deux pour être sûr d'obtenir le bon<br/>
résultat.</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>, qu'il faut<br/>
prouver à part.</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 <code>range</code> fini<br/>
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.</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>

<question type="multichoice">
  <name>
    <text>Invariants et terminaison — Q29 : Effet d'une assertion fausse</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Pendant l'exécution d'un programme Python, la condition d'une<br/>
instruction <code>assert</code> s'avère fausse. Que se passe-t-il ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p><code>assert condition</code> vérifie une hypothèse à un instant précis de<br/>
l'exécution. Tant que la condition est vraie, l'instruction est<br/>
sans effet ; dès qu'elle est fausse, le programme s'arrête avec une<br/>
<code>AssertionError</code>, ce qui évite qu'une erreur se propage en silence.</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>Le programme s'arrête aussitôt en levant une <code>AssertionError</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : une assertion fausse interrompt l'exécution en<br/>
signalant la ligne fautive. C'est ce qui en fait un outil de<br/>
détection : l'erreur apparaît au plus près de sa cause.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>L'instruction est ignorée et le programme continue normalement</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : une assertion n'est pas un simple commentaire. Si sa<br/>
condition est fausse, l'exécution s'arrête sur une<br/>
<code>AssertionError</code>.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Python corrige la valeur fautive pour rendre la condition vraie</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : une assertion vérifie, elle ne répare rien. Python ne<br/>
sait pas quelle valeur serait correcte, il signale seulement que<br/>
l'hypothèse du programmeur est violée.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>La fonction en cours renvoie <code>False</code> et l'exécution se poursuit</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : <code>assert</code> ne renvoie aucune valeur. Une condition fausse<br/>
déclenche une erreur qui arrête le programme.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Invariants et terminaison — Q30 : Précondition d'une division</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>La fonction suivante ne doit être appelée qu'avec un argument non<br/>
nul :<br/>
<pre><code>def inverse(x):
    return 1 / x</code></pre><br/>
Quelle instruction, placée en première ligne du corps de la<br/>
fonction, exprime cette précondition ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Une précondition s'écrit comme une assertion sur les arguments,<br/>
placée au début de la fonction. Elle doit être exactement aussi<br/>
stricte que nécessaire, ni plus, ni moins.</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>assert x != 0</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : la précondition porte sur l'argument reçu, avant<br/>
tout calcul. Si l'appelant fournit <code>0</code>, l'assertion arrête le<br/>
programme avec un message clair au lieu de laisser la division<br/>
échouer.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p><code>assert x &gt; 0</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : cette condition rejette aussi les nombres négatifs, pour<br/>
lesquels l'inverse existe pourtant. La précondition serait plus<br/>
restrictive que nécessaire.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p><code>assert 1 / x != 0</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : pour évaluer cette condition, Python calcule d'abord<br/>
<code>1 / x</code>. Avec <code>x</code> égal à <code>0</code>, la division échoue avant même que<br/>
l'assertion ne soit testée.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p><code>assert x == 0</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : la condition est inversée. Elle arrêterait le programme<br/>
pour tous les arguments valides et laisserait passer le seul cas<br/>
interdit.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Invariants et terminaison — Q31 : Postcondition d'une fonction de tri</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Une fonction <code>trier(t)</code> doit réordonner la liste <code>t</code> par ordre<br/>
croissant, en acceptant les valeurs répétées. Quelle assertion,<br/>
placée juste avant le <code>return</code>, vérifie correctement cette<br/>
postcondition ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Une postcondition décrit le résultat garanti par la fonction. Pour<br/>
un tri, c'est l'ordre croissant au sens large : chaque élément est<br/>
inférieur ou égal à son voisin de droite. L'assertion doit tester<br/>
exactement cette propriété, sur 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[<pre><code>for i in range(len(t) - 1):
    assert t[i] &lt;= t[i + 1]</code></pre>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : une liste est triée par ordre croissant si<br/>
chaque élément est inférieur ou égal au suivant. Le parcours<br/>
vérifie cette propriété pour tous les couples d'éléments<br/>
voisins.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<pre><code>for i in range(len(t) - 1):
    assert t[0] &lt;= t[i + 1]</code></pre>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : cette boucle vérifie seulement que le premier élément<br/>
est le plus petit. La liste <code>[1, 5, 3, 7]</code> passe ce test sans<br/>
être triée.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<pre><code>for i in range(len(t) - 1):
    assert t[i] &lt; t[i + 1]</code></pre>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : l'inégalité stricte interdit les valeurs répétées. La<br/>
liste <code>[2, 2, 3]</code> est pourtant correctement triée, et cette<br/>
assertion l'arrêterait.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<pre><code>for i in range(len(t)):
    assert t[i] &lt;= t[i + 1]</code></pre>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : au dernier tour, <code>i</code> vaut <code>len(t) - 1</code> et <code>t[i + 1]</code><br/>
désigne un indice hors limites. L'assertion échoue par une<br/>
erreur d'indice, même sur une liste triée.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Invariants et terminaison — Q32 : Une assertion avec message</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Que se passe-t-il à l'exécution de <code>assert n &gt; 0, "n doit être<br/>
strictement positif"</code> lorsque <code>n</code> vaut <code>-3</code> ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Un message d'assertion rend l'erreur lisible : au lieu d'une<br/>
condition cryptique, le programmeur voit l'hypothèse violée en<br/>
français.</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>Le programme s'arrête, l'erreur affichant le message</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : le texte après la virgule accompagne l'erreur.<br/>
Il explique au programmeur quelle hypothèse a été violée.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Le message est affiché et le programme continue normalement</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : une assertion fausse interrompt toujours le programme.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Le message est ignoré, <code>assert</code> n'acceptant qu'une condition</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : le second argument, facultatif, est bien pris en<br/>
compte et affiché avec l'erreur.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p><code>n</code> est remplacé par <code>3</code>, valeur absolue de <code>-3</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : une assertion ne corrige rien, elle signale.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Invariants et terminaison — Q33 : Le coût d'une assertion dans une boucle</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Pour vérifier l'invariant d'un tri, Nora ajoute dans la boucle<br/>
principale une assertion qui parcourt toute la partie triée. Quelle<br/>
conséquence ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Les assertions sont un outil de développement : on accepte leur<br/>
coût pour traquer les erreurs, puis on les allège dans la version<br/>
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>Un ralentissement net, l'assertion parcourant la liste à chaque tour</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : un parcours par tour sur $n$ tours ajoute un<br/>
coût quadratique. Utile pour mettre au point, l'assertion se<br/>
retire ou se désactive une fois le programme validé.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Aucune conséquence, une assertion ne coûtant rien à l'exécution</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : l'expression de l'assertion est évaluée à chaque<br/>
passage, avec son coût propre.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Le tri devient incorrect, l'assertion modifiant la liste pendant le parcours</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : une assertion bien écrite ne modifie rien ; elle lit<br/>
seulement.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Le programme refuse de démarrer, une assertion étant interdite dans une boucle</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : rien n'interdit une assertion dans une boucle, c'est<br/>
même courant pendant la mise au point.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Invariants et terminaison — Q34 : Compter les tours grâce au variant</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Combien de tours effectue cette boucle, et quel variant permet de<br/>
prouver qu'elle termine ?<br/>
<pre><code>i = 0
while i &lt; 10:
    i = i + 3</code></pre></p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Un variant est une quantité entière, positive tant que la boucle<br/>
tourne, et qui décroît strictement à chaque tour : ici <code>10 - i</code>.</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>$4$ tours ; le variant est <code>10 - i</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : <code>10 - i</code> est un entier qui diminue strictement<br/>
à chaque tour et la boucle s'arrête dès qu'il devient négatif<br/>
ou nul. <code>i</code> prend les valeurs $3$, $6$, et ainsi de suite,<br/>
jusqu'à atteindre ou dépasser $10$ en $4$ tours.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>$3$ tours ; le variant est <code>i</code>, qui augmente</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : <code>i</code> augmente, il ne peut pas servir de variant, et le<br/>
dernier tour, qui fait dépasser $10$, compte aussi.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>$10$ tours ; le variant est <code>i</code>, de $1$ en $1$</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : <code>i</code> avance de $3$ en $3$, pas de $1$ en $1$.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Une infinité de tours, <code>i</code> ne valant jamais exactement $10$</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : la condition est <code>i &lt; 10</code>, pas <code>i != 10</code> ; dépasser<br/>
$10$ suffit à sortir.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Invariants et terminaison — Q35 : Un variant pour une variable qui augmente</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Quel variant prouve la terminaison de cette boucle, où <code>n</code> est un<br/>
entier positif ?<br/>
<pre><code>x = 0
while x * x &lt; n:
    x = x + 1</code></pre></p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Quand une variable grandit vers une borne, le variant est la<br/>
distance à cette borne : <code>n - x</code> ou <code>n - x * x</code>.</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 - x</code>, qui diminue de $1$ à chaque tour</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : tant que la boucle tourne, <code>x * x &lt; n</code> impose<br/>
<code>x &lt; n</code>, donc <code>n - x</code> est strictement positif, et chaque tour le<br/>
réduit de $1$.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p><code>x</code>, qui augmente de $1$ à chaque tour</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : un variant doit décroître ; une quantité qui augmente<br/>
ne borne pas le nombre de tours.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p><code>x * x</code>, qui finit par dépasser <code>n</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : <code>x * x</code> augmente lui aussi ; c'est l'écart avec <code>n</code><br/>
qui diminue.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p><code>n</code>, qui est positif pendant toute la boucle</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : <code>n</code> ne change pas pendant la boucle, il ne décroît<br/>
donc pas.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Invariants et terminaison — Q36 : L'invariant d'un calcul de puissance</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Quel invariant relie <code>p</code> et <code>i</code> à chaque passage dans la condition<br/>
de cette boucle ?<br/>
<pre><code>p = 1
i = 0
while i &lt; n:
    p = p * 2
    i = i + 1</code></pre></p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>L'invariant <code>p = 2^i</code> décrit ce que la boucle a construit jusqu'à<br/>
présent ; combiné à la condition de sortie, il prouve le résultat.</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>p</code> vaut $2^{i}$</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : vrai au départ, $p = 1 = 2^0$, et conservé par<br/>
chaque tour, qui double <code>p</code> et augmente <code>i</code> de $1$. À la sortie,<br/>
<code>i</code> vaut <code>n</code> et <code>p</code> vaut $2^n$.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p><code>p</code> vaut $2 \times i$</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : après deux tours, <code>p</code> vaut $4$ et <code>i</code> vaut $2$, mais<br/>
après trois tours <code>p</code> vaut $8$ et $2 \times 3 = 6$.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p><code>p</code> vaut $i^2$</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : après trois tours, <code>p</code> vaut $8$ et $i^2$ vaut $9$.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p><code>p</code> vaut $n$</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : <code>p</code> change à chaque tour, il ne peut pas rester égal à<br/>
<code>n</code>.</p>]]></text>
    </feedback>
  </answer>
</question>

</quiz>
