<?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 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="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>
  <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="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>
</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>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="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="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>
  <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>
</question>

<question type="multichoice">
  <name>
    <text>Invariants et terminaison — Q03 : Variant de boucle</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Pour prouver la terminaison d'une boucle while,<br/>
on cherche un <strong>variant</strong>. Quelle propriété<br/>
doit-il avoir ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Variant typique : pour la dichotomie, c'est la<br/>
<strong>taille de l'intervalle</strong> d - g qui décroît<br/>
strictement. Pour while x &gt; 0: x -= 1, c'est<br/>
x lui-même.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="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>Ê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>
  <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="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>
</question>

<question type="multichoice">
  <name>
    <text>Invariants et terminaison — Q04 : Exemple : recherche linéaire</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Dans une recherche linéaire avec for i in<br/>
range(len(liste)), quel est l'<strong>invariant</strong> à<br/>
l'entrée du tour i ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Combiner invariant + condition de sortie : à la<br/>
sortie (i = n et pas de return), invariant + (i<br/>
= n) ⇒ « cible absente ». L'invariant est l'âme<br/>
de la preuve.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>La 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 i</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : à l'entrée de l'itération<br/>
i, on a déjà testé les indices 0 à i-1 et<br/>
aucun n'a satisfait le critère. Si on en<br/>
avait trouvé un, on aurait fait un return.</p>]]></text>
    </feedback>
  </answer>
  <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 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>
</question>

<question type="multichoice">
  <name>
    <text>Invariants et terminaison — Q05 : Variant for vs while</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Pour une boucle for i in range(n):, est-il<br/>
nécessaire de prouver la terminaison ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Astuce : si possible, écrire for plutôt que<br/>
while pour éviter de devoir prouver la<br/>
terminaison. C'est aussi plus lisible.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Non, un for sur un range fini termine seul</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : Python garantit la<br/>
terminaison d'un for sur un range fini<br/>
ou une liste finie. Pas besoin de variant.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>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="0" format="html">
    <text><![CDATA[<p>Oui, comme pour toute boucle</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Trop strict : la terminaison est<br/>
<strong>automatique</strong> pour une boucle for sur un<br/>
range ou une liste.</p>]]></text>
    </feedback>
  </answer>
  <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>
</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>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="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>
  <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="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>
</question>

<question type="multichoice">
  <name>
    <text>Invariants et terminaison — Q07 : Invariant : somme</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>`<code>python<br/>
somme = 0<br/>
for x in liste:<br/>
    somme += x<br/>
</code>`<br/>
Quel est l'invariant après k itérations ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>C'est l'invariant le plus simple à formuler :<br/>
« la variable accumule progressivement ce<br/>
qu'elle doit ». Ce schéma apparaît dans tous<br/>
les calculs incrémentaux.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>somme 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 somme peut donc être<br/>
négative ou nulle à tout moment.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>somme 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, somme contient la somme des k<br/>
éléments déjà parcourus. À la sortie<br/>
(k = n), c'est la somme totale.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>somme vaut le premier élément liste[0] 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="0" format="html">
    <text><![CDATA[<p>somme garde la valeur 0 tant que la boucle tourne</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : somme est modifiée à chaque tour<br/>
par somme += x ; elle ne reste nulle que si<br/>
tous les éléments parcourus sont nuls.</p>]]></text>
    </feedback>
  </answer>
</question>

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

<question type="multichoice">
  <name>
    <text>Invariants et terminaison — Q09 : Boucle infinie</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>`<code>python<br/>
i = 0<br/>
while i &lt; 10:<br/>
    print(i)<br/>
</code>`<br/>
Pourquoi cette boucle ne termine-t-elle pas ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Bug très classique chez les débutants : oublier<br/>
de modifier la variable de boucle. Toujours<br/>
vérifier qu'un variant décroît à chaque tour.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Parce que la condition i &lt; 10 n'est testée qu'une seule fois, au départ</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : la condition d'un while est<br/>
réévaluée avant chaque tour. Ici elle est<br/>
bien retestée, mais reste vraie à chaque<br/>
fois parce que i vaut toujours 0.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Parce que i n'est jamais modifié : il n'y a pas de variant qui décroît</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : la condition i &lt; 10 reste<br/>
toujours vraie. Pas de progression vers la<br/>
terminaison. Solution : ajouter i += 1<br/>
dans la boucle.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Parce que la condition devrait être i &lt;= 10 et non i &lt; 10</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : la borne n'est pas en cause. Avec<br/>
i &lt;= 10, la boucle ne terminerait pas<br/>
davantage, car i ne change jamais.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Parce que print(i) modifie la valeur de i à chaque tour</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : print se contente d'afficher son<br/>
argument, il ne le modifie pas. C'est<br/>
justement parce que rien ne modifie i que<br/>
la condition reste vraie.</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 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>
  <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 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>
</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>Cinq</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : trois suffisent.</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>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>
</question>

<question type="multichoice">
  <name>
    <text>Invariants et terminaison — Q12 : Invariant : minimum</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>`<code>python<br/>
m = liste[0]<br/>
for i in range(1, len(liste)):<br/>
    if liste[i] &lt; m:<br/>
        m = liste[i]<br/>
</code>`<br/>
Quel est l'invariant après l'itération sur les<br/>
k premiers éléments ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Schéma « accumulateur » : la variable m<br/>
agrège progressivement la propriété (ici, le<br/>
min) sur les éléments parcourus.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>m vaut le dernier élément examiné par la boucle</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : m 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="0" format="html">
    <text><![CDATA[<p>m 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>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>m est le minimum des k premiers éléments parcourus</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : à chaque tour, on met à<br/>
jour m si l'élément courant est plus<br/>
petit. À la fin, c'est le min de toute la<br/>
liste.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>m vaut toujours le premier élément liste[0]</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : m est mis à jour dès qu'un<br/>
élément plus petit que lui est rencontré.</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>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>
  <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 d - g + 1 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>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>
</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 ≥ 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>
<p>`<code>python<br/>
def f(n):<br/>
    while n != 1:<br/>
        if n % 2 == 0:<br/>
            n = n // 2<br/>
        else:<br/>
            n = 3 * n + 1<br/>
</code>`</p>
<p>Que peut-on affirmer sur la terminaison de cette boucle pour tout<br/>
entier n ≥ 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="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 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 3 * n + 1, 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>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Elle ne termine pas pour tout n, puisque 3 * n + 1 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="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>
</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 (assert) 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="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>
  <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>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 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>
</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>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 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="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>
  <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>
</question>

<question type="multichoice">
  <name>
    <text>Invariants et terminaison — Q17 : Invariant : compteur d'occurrences</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>`<code>python<br/>
c = 0<br/>
for i in range(len(liste)):<br/>
    if liste[i] == cible:<br/>
        c = c + 1<br/>
</code><br/>
Quel invariant est vérifié à l'entrée du tour<br/>
i, avant le test liste[i] == cible` ?</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 c représente pour<br/>
la partie déjà parcourue, les éléments situés<br/>
avant l'indice i. À la sortie<br/>
(i = len(liste)), il donne la postcondition :<br/>
c 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="0" format="html">
    <text><![CDATA[<p>c est le nombre d'éléments différents de cible avant l'indice i</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/>
[3, 7, 3, 3] avec cible = 3, c vaut 1<br/>
alors qu'aucun élément déjà vu n'est<br/>
différent de 3.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>c vaut i, le nombre de tours déjà effectués</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : c ne compte que les tours où le<br/>
test a réussi. Sur [3, 7, 3, 3] avec<br/>
cible = 3, à l'entrée du tour 2 on a<br/>
i = 2 mais c = 1.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>c est le nombre d'occurrences de cible 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, c vaut 0 alors que<br/>
[3, 7, 3, 3] contient trois fois la<br/>
cible 3.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>c est le nombre d'occurrences de cible avant l'indice i</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : avant le tour i, seuls les<br/>
i premiers éléments ont été examinés, et<br/>
c a été incrémenté une fois par occurrence<br/>
rencontrée. Sur liste = [3, 7, 3, 3] et<br/>
cible = 3, c vaut 0, 1, 1, 2 à l'entrée<br/>
des tours 0, 1, 2, 3, puis 3 à la sortie.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Invariants et terminaison — Q18 : Variant multivarié</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Pour la dichotomie itérative, peut-on choisir<br/>
g (l'indice de gauche) seul comme variant ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Astuce : si une variable augmente, prendre son<br/>
complément (par exemple n - i) comme variant.<br/>
Le choix du variant est souvent affaire de<br/>
reformulation.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Non, parce que g n'est pas vraiment un entier</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : g est bien un entier.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Oui, parfait</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : g peut rester constant si c'est<br/>
d qui change.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>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>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Non, g 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 g qui augmente, il<br/>
faut prendre par exemple n - g ou bien<br/>
la taille de l'intervalle d - g.</p>]]></text>
    </feedback>
  </answer>
</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="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>
  <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="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>
</question>

<question type="multichoice">
  <name>
    <text>Invariants et terminaison — Q20 : Outils</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Quel outil aide à <strong>détecter</strong> un bug dans un<br/>
invariant ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Les assert sont une excellente pratique :<br/>
ils transforment des invariants implicites en<br/>
vérifications explicites, attrapant les bugs<br/>
au plus tôt.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Un print() qui signale automatiquement l'invariant faux</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : print 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>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Un assert de l'invariant dans la boucle</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : par exemple<br/>
assert m == min(liste[:i+1]). Si<br/>
l'invariant échoue à un tour, Python lève<br/>
AssertionError et indique le bug.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Un commentaire # TODO 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="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>
</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 liste[0] et le<br/>
minimum en liste[1], ce serait « trié »<br/>
(ordre 1 puis 2 éléments), mais incorrect.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Non, il manque 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>`<code>python<br/>
while a &gt; b:<br/>
    a = a - b<br/>
</code><br/>
(avec a, b entiers, b &gt; 0`). Quel est un<br/>
variant valide ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Cette boucle calcule a mod b (reste de la<br/>
division euclidienne). C'est un cas classique<br/>
illustrant variant et terminaison.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>La quantité b - a</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : tant que la boucle tourne, a &gt; b<br/>
donc b - a 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>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>La variable a</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : à chaque tour a -= b<br/>
avec b &gt; 0, donc a décroît strictement,<br/>
tout en restant strictement positif tant<br/>
que la boucle tourne (a &gt; b &gt; 0). La<br/>
boucle se termine quand a &lt;= b.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>La constante 1</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : une constante ne décroît pas.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>La variable b</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : b ne change pas dans la boucle,<br/>
ce n'est donc pas une quantité décroissante.</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 t :</p>
<p>`<code>python<br/>
def indice_min(t):<br/>
    assert len(t) &gt; 0<br/>
    k = 0<br/>
    for i in range(1, len(t)):<br/>
        if t[i] &lt; t[k]:<br/>
            k = i<br/>
    return k<br/>
</code></p>
<p>On veut vérifier, juste avant return k, la<br/>
postcondition « t[k] est inférieur ou égal à<br/>
chacun des éléments de t` ». Quelles lignes<br/>
conviennent ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Des assertions garantissent des préconditions,<br/>
comme assert len(t) &gt; 0 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[<p>`<code>python<br/>
assert t[k] &lt;= t[i]<br/>
</code>`</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : après la boucle, i vaut le<br/>
dernier indice parcouru, donc on ne compare<br/>
t[k] qu'au dernier élément. Pour une liste<br/>
d'un seul élément, i n'est même pas défini<br/>
et cette ligne provoque une erreur.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>`<code>python<br/>
assert 0 &lt;= k and k &lt; len(t)<br/>
</code>`</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : cette assertion vérifie seulement<br/>
que k est un indice valide. Elle resterait<br/>
vraie si la fonction renvoyait l'indice du<br/>
plus grand élément.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>`<code>python<br/>
for j in range(len(t)):<br/>
    assert t[k] &lt;= t[j]<br/>
</code>`</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : la boucle compare t[k] à<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ù j vaut<br/>
k, ainsi que les minimums en double.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>`<code>python<br/>
for j in range(len(t)):<br/>
    assert t[k] &lt; t[j]<br/>
</code>`</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : pour j égal à k, t[k] &lt; t[k]<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>
</question>

<question type="multichoice">
  <name>
    <text>Invariants et terminaison — Q24 : Inventer l'invariant</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>`<code>python<br/>
r = 0<br/>
n = N<br/>
while n &gt; 0:<br/>
    n = n // 2<br/>
    r = r + 1<br/>
</code>`<br/>
Que calcule cette boucle, et quel invariant<br/>
rend ce calcul évident ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Cet algorithme calcule le <strong>logarithme entier</strong>.<br/>
C'est aussi la base de la complexité O(log n)<br/>
de la dichotomie : on divise par 2 jusqu'à<br/>
atteindre 0.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>La boucle compte simplement de 1 jusqu'à N</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : n est divisé par 2, pas<br/>
décrémenté.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Invariant n == N // 2^r ; r 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 : n (qui décroît<br/>
strictement par division entière).</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>La boucle ne termine jamais, n ne devenant jamais nul</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : n // 2 ramène n à 0 en log₂(N)<br/>
étapes (par exemple 8, 4, 2, 1, 0).</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>r reste égal à 0 pendant toute la boucle</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : r = r + 1 l'incrémente à chaque<br/>
tour.</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="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="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 invariant doit être vrai à chaque entrée d'itération</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Vrai : c'est sa définition.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Toute boucle for i in range(n) se termine, sans qu'on ait besoin de prouver de variant</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Vrai : la boucle for sur un range 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/>
i de la boucle externe, quel invariant<br/>
caractérise correctement l'état de la liste ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Différence clé avec le tri par sélection :<br/>
l'invariant de l'insertion porte sur le tri<br/>
d'une partie initiale (sans hypothèse sur les<br/>
valeurs), alors que celui de la sélection<br/>
ajoute la condition « plus petits que les<br/>
autres ».</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Les i premiers éléments sont les plus grands</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : ce serait un tri décroissant ou<br/>
un tri par sélection inversé. Le tri par<br/>
insertion classique est croissant et ne<br/>
place pas les plus grands en tête.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Les i premiers éléments sont triés et plus petits que tous les autres</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : c'est l'invariant du tri par<br/>
<strong>sélection</strong>. Le tri par insertion ne<br/>
place pas les plus petits en tête à chaque<br/>
étape ; il insère le i-ème élément à sa<br/>
place dans la partie déjà traitée.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>liste[:i+1] 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 i + 1 premiers<br/>
éléments restent les mêmes (à l'ensemble<br/>
près) qu'avant la boucle, mais maintenant<br/>
ordonnés. À la dernière itération<br/>
i = n - 1, toute la liste est triée.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>La liste est entièrement triée</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : trop fort. À l'itération i,<br/>
seuls les i + 1 premiers éléments sont<br/>
triés ; les éléments suivants n'ont pas<br/>
encore été traités.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Invariants et terminaison — Q27 : Terminaison de l'algorithme d'Euclide</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>L'algorithme d'Euclide pour le PGCD s'écrit :<br/>
`<code>python<br/>
def pgcd(a, b):<br/>
    while b != 0:<br/>
        a, b = b, a % b<br/>
    return a<br/>
</code><br/>
(avec a, b entiers naturels, b &gt; 0` à<br/>
l'entrée). Quel est un variant qui prouve la<br/>
terminaison ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Une remarque profonde : ici, l'<strong>invariant</strong><br/>
est pgcd(a, b) = pgcd(a₀, b₀) (la valeur<br/>
initiale du PGCD est conservée), tandis que le<br/>
<strong>variant</strong> est b. À la sortie, l'invariant<br/>
donne pgcd(a, 0) = a, ce qui est bien le<br/>
PGCD recherché.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>La valeur de b</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : à chaque itération, b<br/>
devient a % b, qui est strictement<br/>
inférieur à l'ancien b. Comme b est un<br/>
entier naturel minoré par 0, la suite des<br/>
valeurs de b est strictement décroissante<br/>
et finie. La boucle se termine donc.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Le PGCD lui-même</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : l'invariant de l'algorithme est<br/>
précisément que pgcd(a, b) reste<br/>
constant à chaque itération. Une quantité<br/>
constante ne peut servir de variant (qui<br/>
doit décroître strictement).</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>La valeur de a</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : a ne décroît pas forcément à<br/>
chaque tour. Par exemple avec a = 5,<br/>
b = 12, après une itération on a<br/>
a = 12, b = 5, donc a a augmenté.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>La somme a + b</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : la somme peut augmenter ou<br/>
stagner selon les cas. Par exemple<br/>
pgcd(5, 12) : avant, a + b = 17 ;<br/>
après, a + b = 12 + 5 = 17. Donc pas de<br/>
décroissance stricte.</p>]]></text>
    </feedback>
  </answer>
</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 assert 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="100" format="html">
    <text><![CDATA[<p>Une instruction assert exprimant l'invariant attendu</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : assert lève<br/>
immédiatement une AssertionError si la<br/>
condition est fausse, ce qui localise<br/>
précisément l'itération où l'invariant a<br/>
été rompu. C'est un outil de débogage très<br/>
efficace.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Un commentaire # vérification de l'invariant</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : un commentaire est inerte. Il<br/>
n'est lu que par le programmeur, pas par<br/>
l'interpréteur Python. Aucun bug ne peut<br/>
être détecté ainsi.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Un appel à print affichant la valeur courante de la variable</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Possible mais limité : il faut alors<br/>
inspecter la sortie à l'œil nu et<br/>
identifier visuellement une anomalie. Pas<br/>
de détection automatique.</p>]]></text>
    </feedback>
  </answer>
</question>

<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 assert s'avère fausse. Que se passe-t-il ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>assert condition 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/>
AssertionError, 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 AssertionError</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>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>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/>
AssertionError.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>La fonction en cours renvoie False et l'exécution se poursuit</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : assert 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/>
`<code>python<br/>
def inverse(x):<br/>
    return 1 / x<br/>
</code>`<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="0" format="html">
    <text><![CDATA[<p>assert x &gt; 0</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>assert 1 / x != 0</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : pour évaluer cette condition, Python calcule d'abord<br/>
1 / x. Avec x égal à 0, 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>assert x == 0</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>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>assert x != 0</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 0, l'assertion arrête le<br/>
programme avec un message clair au lieu de laisser la division<br/>
échouer.</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 trier(t) doit réordonner la liste t par ordre<br/>
croissant, en acceptant les valeurs répétées. Quelle assertion,<br/>
placée juste avant le return, 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="0" format="html">
    <text><![CDATA[<p>`<code>python<br/>
for i in range(len(t) - 1):<br/>
    assert t[i] &lt; t[i + 1]<br/>
</code>`</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : l'inégalité stricte interdit les valeurs répétées. La<br/>
liste [2, 2, 3] est pourtant correctement triée, et cette<br/>
assertion l'arrêterait.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>`<code>python<br/>
for i in range(len(t)):<br/>
    assert t[i] &lt;= t[i + 1]<br/>
</code>`</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : au dernier tour, i vaut len(t) - 1 et t[i + 1]<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>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>`<code>python<br/>
for i in range(len(t) - 1):<br/>
    assert t[i] &lt;= t[i + 1]<br/>
</code>`</p>]]></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[<p>`<code>python<br/>
for i in range(len(t) - 1):<br/>
    assert t[0] &lt;= t[i + 1]<br/>
</code>`</p>]]></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 [1, 5, 3, 7] passe ce test sans<br/>
être 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 assert n &gt; 0, "n doit être<br/>
strictement positif" lorsque n vaut -3 ?</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="0" format="html">
    <text><![CDATA[<p>Le message est ignoré, assert 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="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>n est remplacé par 3, valeur absolue de -3</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : une assertion ne corrige rien, elle signale.</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>
</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 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>
  <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>
</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/>
`<code>python<br/>
i = 0<br/>
while i &lt; 10:<br/>
    i = i + 3<br/>
</code>`</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 10 - i.</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>10 tours ; le variant est i, de 1 en 1</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : i 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, i ne valant jamais exactement 10</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : la condition est i &lt; 10, pas i != 10 ; dépasser<br/>
10 suffit à sortir.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>3 tours ; le variant est i, qui augmente</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : i 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="100" format="html">
    <text><![CDATA[<p>4 tours ; le variant est 10 - i</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : 10 - i 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. i prend les valeurs 3, 6, et ainsi de suite,<br/>
jusqu'à atteindre ou dépasser 10 en 4 tours.</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ù n est un<br/>
entier positif ?<br/>
`<code>python<br/>
x = 0<br/>
while x * x &lt; n:<br/>
    x = x + 1<br/>
</code>`</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Quand une variable grandit vers une borne, le variant est la<br/>
distance à cette borne : n - x ou n - x * x.</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>x * x, qui finit par dépasser n</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : x * x augmente lui aussi ; c'est l'écart avec n<br/>
qui diminue.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>n - x, qui diminue de 1 à chaque tour</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : tant que la boucle tourne, x * x &lt; n impose<br/>
x &lt; n, donc n - x est strictement positif, et chaque tour le<br/>
réduit de 1.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>x, 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>n, qui est positif pendant toute la boucle</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : n 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 p et i à chaque passage dans la condition<br/>
de cette boucle ?<br/>
`<code>python<br/>
p = 1<br/>
i = 0<br/>
while i &lt; n:<br/>
    p = p * 2<br/>
    i = i + 1<br/>
</code>`</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>L'invariant p = 2^i 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>p vaut 2ⁱ</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : vrai au départ, p = 1 = 2⁰, et conservé par<br/>
chaque tour, qui double p et augmente i de 1. À la sortie,<br/>
i vaut n et p vaut 2ⁿ.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>p vaut n</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : p change à chaque tour, il ne peut pas rester égal à<br/>
n.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>p vaut i²</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : après trois tours, p vaut 8 et i² vaut 9.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>p vaut 2 × i</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : après deux tours, p vaut 4 et i vaut 2, mais<br/>
après trois tours p vaut 8 et 2 × 3 = 6.</p>]]></text>
    </feedback>
  </answer>
</question>

</quiz>
