<?xml version="1.0" encoding="UTF-8"?>
<quiz>
<question type="category">
  <category>
    <text>$course$/QCM de NSI/Première/Tables de données</text>
  </category>
  <info format="html">
    <text><![CDATA[<p>Représentation tabulaire des données, descripteurs<br/>
(colonnes), enregistrements (lignes), opérations courantes<br/>
(recherche, tri, sélection, fusion, jointure simple), en<br/>
Python avec listes de dictionnaires ou listes de listes.</p>]]></text>
  </info>
</question>

<question type="multichoice">
  <name>
    <text>Tables de données — Q01 : Qu'est-ce qu'une table ?</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>En informatique, qu'appelle-t-on une <strong>table de données</strong> ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Les tables sont la structure la plus simple et la plus répandue pour organiser des données : tableurs, fichiers CSV et bases de données reposent tous sur ce modèle.</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 tableau de lignes (enregistrements) et de colonnes (descripteurs)</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : c'est la définition standard,<br/>
identique à celle d'un tableur ou d'une table<br/>
de base de données. Chaque ligne décrit une<br/>
entité (élève, livre...), chaque colonne un<br/>
attribut (nom, âge...).</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Un fichier texte dont les valeurs sont séparées par des virgules</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : c'est la description du format<br/>
<strong>CSV</strong>, qui n'est qu'un moyen de stocker<br/>
une table dans un fichier. La table<br/>
elle-même est la structure abstraite<br/>
(lignes et colonnes), indépendante de son<br/>
format d'enregistrement.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Une fonction Python qui renvoie un dictionnaire</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : c'est éventuellement un moyen de<br/>
<strong>représenter</strong> une table, pas la définition<br/>
elle-même.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Un type primitif fondamental fourni nativement par Python</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : Python n'a pas de type natif "table".<br/>
On peut la simuler avec des listes ou<br/>
dictionnaires.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Tables de données — Q02 : Vocabulaire</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Comment appelle-t-on une <strong>colonne</strong> dans une table<br/>
de données ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Vocabulaire à maîtriser : ligne = enregistrement<br/>
= entité ; colonne = descripteur = attribut =<br/>
champ. Selon le manuel, le mot peut varier.</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 valeur</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : une valeur est le contenu d'une seule case, à l'intersection d'une ligne et d'une colonne. Une colonne regroupe toutes les valeurs d'un même descripteur.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Une ligne</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : confusion ligne/colonne. Une ligne<br/>
décrit une entité.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Un descripteur (ou attribut, ou champ)</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : la colonne décrit une propriété<br/>
commune à toutes les entités (par exemple<br/>
"nom", "age", "ville"). Les termes<br/>
"descripteur", "attribut", "champ" sont<br/>
synonymes selon le contexte.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Un enregistrement, c'est-à-dire une entité complète de la table</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : un enregistrement est une <strong>ligne</strong>,<br/>
pas une colonne.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Tables de données — Q03 : Liste de dictionnaires</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Comment représente-t-on couramment une table en<br/>
Python (avec en-tête) ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Autres représentations possibles : liste de<br/>
tuples, liste de listes, dict de listes (« colonne<br/>
par colonne »). Le choix dépend de l'usage. Pour<br/>
le NSI Première, on utilise principalement la liste<br/>
de dictionnaires.</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>Comme une seule et longue chaîne de caractères unique</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : ce ne serait pas pratique pour<br/>
manipuler les données.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Comme un entier</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : un entier ne stocke aucune<br/>
structure.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Comme une liste de dictionnaires, un par ligne</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : exemple<br/>
[{"nom":"Alice","age":17}, {"nom":"Bob","age":16}].<br/>
C'est ce que renvoie csv.DictReader quand on<br/>
le convertit en liste. Très lisible<br/>
(ligne["nom"]).</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Comme une fonction</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : une fonction décrit un calcul, pas<br/>
des données.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Tables de données — Q04 : Accéder à une cellule</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Soit<br/>
`<code>python<br/>
table = [<br/>
    {"nom": "Alice", "age": 17},<br/>
    {"nom": "Bob", "age": 16}<br/>
]<br/>
</code>`<br/>
Comment accéder à l'âge de Bob ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Schéma général : table[indice_ligne][descripteur].<br/>
L'ordre des accès reflète la structure : d'abord<br/>
la liste, puis le dictionnaire.</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>table[2]['age']</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : indice <strong>hors-borne</strong>. Avec deux<br/>
lignes, les indices valides sont 0 et 1, pas<br/>
2 (IndexError).</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>table[1]['age']</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : Bob est la deuxième ligne<br/>
(indice 1), et 'age' est le descripteur. On<br/>
obtient 16.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>table.age[1]</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : aucune méthode ni attribut .age sur<br/>
une liste (AttributeError).</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>table['Bob']['age']</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : table est une <strong>liste</strong>, pas un<br/>
dictionnaire indexé par nom. Cela lève<br/>
TypeError.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Tables de données — Q05 : Parcourir une table</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Pour afficher tous les noms d'élèves d'une table<br/>
(liste de dictionnaires avec une clé "nom"), quel<br/>
code utilise-t-on ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Schéma classique de parcours d'une liste de<br/>
dictionnaires. À retenir.</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 ligne in table:<br/>
    print(table["nom"])<br/>
</code>`</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : dans la boucle, c'est ligne qu'il<br/>
faut indexer. table est une liste, on ne<br/>
peut pas l'indexer par une chaîne : TypeError.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>`<code>python<br/>
for ligne in table:<br/>
    print(ligne.nom)<br/>
</code>`</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : un dictionnaire n'a pas d'attribut<br/>
.nom, cette écriture lève AttributeError.<br/>
La valeur d'une clé s'obtient avec des<br/>
crochets : ligne["nom"].</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>`<code>python<br/>
for ligne in table:<br/>
    print(ligne["nom"])<br/>
</code>`</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : la boucle parcourt chaque<br/>
dictionnaire, et on accède à la valeur de la<br/>
clé "nom".</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>`<code>python<br/>
for nom in table:<br/>
    print(nom)<br/>
</code>`</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : la variable nom recevrait chaque<br/>
<strong>dictionnaire</strong> entier, pas le nom seulement.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Tables de données — Q06 : Origine des tables</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>D'où peut provenir une table de données dans un<br/>
projet réel ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Une compétence clé de NSI : savoir lire des données réelles, souvent en CSV, les transformer en table Python, puis les manipuler.</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>Uniquement de données saisies à la main au clavier</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Trop restrictif : une table peut aussi provenir d'un fichier, d'un tableur ou d'un capteur, sans aucune saisie manuelle.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Uniquement d'un fichier CSV créé à la main</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Trop restrictif : il existe de nombreuses<br/>
autres sources.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>D'un fichier CSV, d'un tableur, de données ouvertes...</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : les tables sont partout en informatique. Données ouvertes (data.gouv.fr), exports de tableur, relevés de capteurs, fichiers CSV : autant de sources possibles.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Uniquement d'un tableur comme LibreOffice Calc</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Trop restrictif : un tableur est une source fréquente, mais pas la seule.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Tables de données — Q07 : Recherche par critère</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Pour trouver toutes les lignes où l'âge est<br/>
strictement supérieur à 16, quel code écrit-on ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Compréhension de liste : schéma Python élégant<br/>
pour filtrer, transformer et combiner. Très<br/>
utilisé sur les tables.</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>python<br/>
[ligne for ligne in table if ligne["age"] &gt; 16]<br/>
</code>`</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : compréhension de liste avec<br/>
condition. Forme idiomatique en Python pour<br/>
filtrer.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>`<code>python<br/>
table.find(age &gt; 16)<br/>
</code>`</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : la méthode .find() n'existe pas<br/>
sur les listes.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>`<code>python<br/>
table[ligne["age"] &gt; 16]<br/>
</code>`</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : syntaxe invalide. ligne n'est pas<br/>
défini hors d'une boucle.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>`<code>python<br/>
for ligne in table:<br/>
    if ligne["age"] &gt; 16:<br/>
        print(ligne)<br/>
</code>`</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Cela <strong>affiche</strong> les lignes mais ne renvoie<br/>
pas une liste. Si la question est "trouver",<br/>
on attend une valeur de retour, pas un<br/>
affichage.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Tables de données — Q08 : Construire depuis CSV</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Quel est le moyen le plus simple de construire une<br/>
table (liste de dictionnaires) à partir d'un fichier<br/>
CSV avec en-tête ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Idiome standard. Penser à fermer le fichier<br/>
proprement avec un with, ou utiliser cette<br/>
écriture compacte si le fichier est petit.</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>Lire le fichier ligne par ligne et coder à la main le découpage</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : possible mais fastidieux et fragile<br/>
(séparateur, guillemets, en-tête). Le module<br/>
csv fait ce découpage pour nous.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>list(csv.DictReader(open('data.csv', encoding='utf-8')))</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : csv.DictReader fournit une suite de dictionnaires, un par ligne, avec pour clés les noms de l'en-tête ; list() les rassemble en une table prête à l'emploi.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>csv.load('data.csv') (cette fonction existe-t-elle ?)</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : cette fonction n'existe pas dans le<br/>
module csv (AttributeError).</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>list(csv.reader(open('data.csv', encoding='utf-8')))</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : csv.reader produit des <strong>listes</strong>,<br/>
pas des dictionnaires, et la ligne d'en-tête<br/>
est lue comme les autres. Sur un fichier<br/>
nom,age on obtient<br/>
[['nom', 'age'], ['Alice', '17'], ...], sans<br/>
accès par descripteur.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Tables de données — Q09 : Nombre de lignes</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Comment obtenir le <strong>nombre d'enregistrements</strong><br/>
(lignes) d'une table représentée comme liste de<br/>
dictionnaires ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Pour le nombre de <strong>colonnes</strong>, on regarde les<br/>
clés du premier dictionnaire :<br/>
len(table[0]) (en supposant la table non vide).</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>len(table)</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : len() sur la liste donne le<br/>
nombre de dictionnaires, donc de lignes.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>size(table)</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : pas de fonction size en Python<br/>
standard.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>len(table.keys())</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : .keys() n'existe pas sur une<br/>
liste. Cela lève AttributeError.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>table.length</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : les listes Python n'ont pas d'attribut length, nom utilisé dans d'autres langages comme JavaScript. Cette écriture lève AttributeError ; en Python, on utilise la fonction len.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Tables de données — Q10 : Table vide</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Que vaut len(table) pour une table vide ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Toujours penser au cas de la table vide dans les<br/>
calculs : moyenne = total / len(table) lèverait<br/>
ZeroDivisionError.</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 est levée</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : len([]) renvoie 0 sans erreur.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>None</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : len renvoie toujours un entier.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>-1</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : len n'est jamais négatif.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>0</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : [] (liste vide) contient<br/>
zéro élément.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Tables de données — Q11 : Trier par descripteur</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>On dispose de la fonction clé<br/>
`<code>python<br/>
def age(ligne):<br/>
    return ligne["age"]<br/>
</code>`<br/>
Comment trier la table par âge <strong>croissant</strong> ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Pour trier sans modifier la table d'origine :<br/>
sorted(table, key=age). Pour un tri<br/>
<strong>décroissant</strong>, ajouter reverse=True. On passe<br/>
la fonction elle-même (age, sans parenthèses) :<br/>
c'est sort qui l'appelle sur chaque ligne.</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>sorted(table, by=age)</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : sorted n'a pas d'argument by<br/>
(TypeError). C'est key= qu'il faut.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>table.sort(key=age)</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : key indique la fonction qui<br/>
calcule, pour chaque ligne, la valeur sur<br/>
laquelle comparer. Ici age renvoie l'âge de<br/>
la ligne. Tri en place de la liste.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>table.sort(reverse=False)</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : reverse=False est déjà la valeur<br/>
par défaut, et il manque key : sans lui,<br/>
sort ne sait pas comparer deux<br/>
dictionnaires entre eux (TypeError).</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>table.sort(age)</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : sort n'accepte aucun argument<br/>
positionnel (TypeError). La fonction de clé<br/>
doit être nommée : key=age.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Tables de données — Q12 : Sélectionner des colonnes</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Comment construire une nouvelle table resultat ne<br/>
contenant que les colonnes nom et age de table<br/>
(sans les autres descripteurs) ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Cette opération consiste à <strong>extraire un<br/>
sous-ensemble de colonnes</strong> d'une table (on parle<br/>
aussi de projection). C'est l'une des manipulations<br/>
classiques de tables, au même titre que la<br/>
sélection de lignes, le tri ou la fusion. En<br/>
compréhension de liste :<br/>
[{"nom": l["nom"], "age": l["age"]} for l in table].</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/>
resultat = {}<br/>
for l in table:<br/>
    for k in ["nom", "age"]:<br/>
        resultat[k] = l[k]<br/>
</code>`</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : resultat est un <strong>dictionnaire</strong><br/>
unique dont on écrase les deux valeurs à chaque<br/>
ligne. On obtient le nom et l'âge de la dernière<br/>
ligne seulement, et non une table.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>`<code>python<br/>
resultat = []<br/>
for l in table:<br/>
    resultat.append({"nom": l["nom"], "age": l["age"]})<br/>
</code>`</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : pour chaque ligne, on construit<br/>
un nouveau dictionnaire ne gardant que les deux<br/>
clés voulues, et on l'ajoute à la nouvelle<br/>
table.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>`<code>python<br/>
resultat = []<br/>
for l in table:<br/>
    for k in ["nom", "age"]:<br/>
        resultat.append({k: l[k]})<br/>
</code>`</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : chaque tour ajoute un dictionnaire à<br/>
<strong>une seule</strong> clé. La table obtenue compte deux<br/>
fois plus de lignes que l'originale, le nom et<br/>
l'âge d'un même élève étant séparés sur deux<br/>
lignes.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>`<code>python<br/>
resultat = []<br/>
for l in table:<br/>
    resultat.append(l[["nom", "age"]])<br/>
</code>`</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : un dictionnaire ne s'indexe pas par une liste de clés, l[["nom", "age"]] lève TypeError. Il faut extraire chaque clé séparément.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Tables de données — Q13 : Fusion de tables</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Soient deux tables t1 et t2 ayant les <strong>mêmes descripteurs</strong>. Comment obtenir une nouvelle table<br/>
contenant toutes les lignes de t1 puis celles de<br/>
t2 ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Pour modifier t1 <strong>en place</strong> au lieu de créer<br/>
une nouvelle table : t1 += t2, ou une boucle<br/>
qui ajoute chaque ligne de t2 avec append.</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>t1.append(t2)</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Attention : append(t2) ajouterait t2<br/>
comme <strong>un seul élément</strong> (une liste de<br/>
listes), pas en fusionnant. Pour ajouter<br/>
les lignes une à une, il faudrait une<br/>
boucle : for ligne in t2: t1.append(ligne).</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>t1.merge(t2)</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : les listes n'ont pas de méthode .merge, cette écriture lève AttributeError.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>fusion(t1, t2)</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : pas de fonction fusion en Python<br/>
standard.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>t1 + t2</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : la concaténation de listes<br/>
(+) crée une nouvelle liste contenant tous<br/>
les éléments. Idiome Python standard.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Tables de données — Q14 : Calculer une moyenne</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Comment calculer la <strong>moyenne</strong> des âges d'une<br/>
table avec un descripteur age (entier) ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Penser au cas de la table <strong>vide</strong>, qui provoquerait une division par zéro : tester len(table) &gt; 0 avant le calcul.</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>sum([ligne.age for ligne in table]) / len(table)</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : un dictionnaire n'a pas d'attribut<br/>
.age (AttributeError). La valeur d'un<br/>
descripteur s'obtient par ligne['age'].</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>sum([ligne['age'] for ligne in table]) / len(table[0])</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : len(table[0]) compte les<br/>
<strong>descripteurs</strong> de la première ligne (le<br/>
nombre de colonnes), pas le nombre de lignes.<br/>
Il faut diviser par len(table).</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>sum([ligne['age'] for ligne in table]) / len(table)</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : la compréhension construit la liste des âges, sum les additionne, puis on divise par le nombre de lignes.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>sum(table['age']) / len(table)</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : table est une <strong>liste</strong>, on ne<br/>
peut pas l'indexer par chaîne. Lève<br/>
TypeError.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Tables de données — Q15 : Jointure simple</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Soient<br/>
`<code>python<br/>
eleves = [<br/>
    {"id": 1, "nom": "Alice"},<br/>
    {"id": 2, "nom": "Bob"}<br/>
]<br/>
notes = [<br/>
    {"id_eleve": 1, "matiere": "Maths", "note": 15},<br/>
    {"id_eleve": 2, "matiere": "NSI", "note": 18}<br/>
]<br/>
</code>`<br/>
Pour associer chaque note au nom de l'élève, on<br/>
effectue une <strong>jointure</strong>. Quel code l'implémente<br/>
correctement ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>C'est l'opération de <strong>fusion</strong> de deux tables sur<br/>
une clé commune. Pour gagner en performance, on<br/>
peut indexer eleves par id dans un dictionnaire<br/>
au préalable.</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 n in notes:<br/>
    for e in eleves:<br/>
        print(e["nom"], n["matiere"], n["note"])<br/>
</code>`</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : sans la condition d'égalité<br/>
n["id_eleve"] == e["id"], on produit le<br/>
<strong>produit cartésien</strong> : chaque note est<br/>
associée à <strong>tous</strong> les élèves, pas au sien<br/>
(quatre lignes affichées au lieu de deux).</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>`<code>python<br/>
for n in notes:<br/>
    print(eleves[n["id_eleve"]]["nom"], n["matiere"], n["note"])<br/>
</code>`</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : eleves[1] accède à l'<strong>indice 1</strong><br/>
de la liste, pas à l'élève d'id 1. Ici la<br/>
note de Maths est attribuée à Bob, puis<br/>
eleves[2] lève IndexError. Un identifiant<br/>
n'est pas un indice.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>`<code>python<br/>
for n in notes:<br/>
    for e in eleves:<br/>
        if n["id_eleve"] == e["id"]:<br/>
            print(e["nom"], n["matiere"], n["note"])<br/>
</code>`</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : on parcourt les notes et,<br/>
pour chacune, on cherche l'élève<br/>
correspondant. On affiche Alice Maths 15<br/>
puis Bob NSI 18. Complexité O(n × m).</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>`<code>python<br/>
for n in notes:<br/>
    for e in eleves:<br/>
        if n["id_eleve"] == e["id_eleve"]:<br/>
            print(e["nom"], n["matiere"], n["note"])<br/>
</code>`</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : la clé commune ne porte pas le même<br/>
nom dans les deux tables : "id" dans<br/>
eleves, "id_eleve" dans notes.<br/>
e["id_eleve"] lève donc KeyError dès la<br/>
première comparaison.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Tables de données — Q16 : Pièges de conversion</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Après lecture d'un CSV avec csv.DictReader, on<br/>
veut calculer la moyenne des âges. Quel piège<br/>
faut-il éviter ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Piège classique chez les débutants : oublier la<br/>
conversion. Symptôme : addition qui concatène<br/>
des chaînes ou comparaison qui plante.</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>Toujours initialiser une variable globale</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Pas un piège spécifique au CSV.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Oublier de convertir les valeurs en int (les valeurs lues sont des chaînes)</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : csv.DictReader ne fait<br/>
aucune conversion de type. "17" + "16"<br/>
donne "1716", pas 33. Toujours convertir<br/>
avant de calculer.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Le module csv ne gère pas les fichiers de plus de 100 lignes</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : il gère sans problème des fichiers de<br/>
plusieurs millions de lignes.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Il faut payer une licence pour utiliser csv.DictReader</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : le module csv est gratuit et inclus<br/>
dans Python standard.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Tables de données — Q17 : Compter par catégorie</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Soit<br/>
`<code>python<br/>
table = [<br/>
    {"nom": "Alice", "ville": "Lyon"},<br/>
    {"nom": "Bob", "ville": "Paris"},<br/>
    {"nom": "Chloé", "ville": "Lyon"}<br/>
]<br/>
</code><br/>
Quel code construit le dictionnaire c donnant le<br/>
nombre d'élèves dans chaque ville, ici<br/>
{"Lyon": 2, "Paris": 1}` ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Schéma général du comptage par catégorie : un<br/>
dictionnaire dont les clés sont les catégories et<br/>
les valeurs les effectifs. Le test if v in c<br/>
distingue la première rencontre d'une catégorie<br/>
(création de la clé) des suivantes (incrément).</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/>
c = {}<br/>
for ligne in table:<br/>
    v = ligne["ville"]<br/>
    c[v] = 1<br/>
</code>`</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : sans test, chaque rencontre d'une ville remet sa valeur à 1, même quand la clé existe déjà. Lyon, rencontrée deux fois, reste à 1 : on obtient {"Lyon": 1, "Paris": 1}.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>`<code>python<br/>
c = {}<br/>
for ligne in table:<br/>
    v = ligne["ville"]<br/>
    if v in c:<br/>
        c[v] = 1<br/>
    else:<br/>
        c[v] = c[v] + 1<br/>
</code>`</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : les deux branches sont inversées. À la<br/>
première rencontre d'une ville, la clé v<br/>
n'existe pas encore dans c, et c[v] + 1<br/>
lève KeyError (ici dès "Lyon"). C'est la<br/>
première rencontre qui doit créer la clé à 1.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>`<code>python<br/>
c = {}<br/>
for ligne in table:<br/>
    v = ligne["ville"]<br/>
    if v in table:<br/>
        c[v] = c[v] + 1<br/>
    else:<br/>
        c[v] = 1<br/>
</code>`</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : le test d'appartenance porte sur<br/>
table, qui ne contient que des dictionnaires,<br/>
jamais une chaîne : il est toujours faux et<br/>
chaque ville est remise à 1. On obtient<br/>
{"Lyon": 1, "Paris": 1} : une présence, pas<br/>
un comptage.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>`<code>python<br/>
c = {}<br/>
for ligne in table:<br/>
    v = ligne["ville"]<br/>
    if v in c:<br/>
        c[v] = c[v] + 1<br/>
    else:<br/>
        c[v] = 1<br/>
</code>`</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : on construit progressivement<br/>
un dictionnaire ville → effectif. À la<br/>
première rencontre d'une ville, on crée la clé<br/>
avec la valeur 1 ; ensuite, on incrémente.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Tables de données — Q18 : Une clé de tri négative</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Soit<br/>
``python<br/>
coureurs = [{"nom": "Lou", "temps": 52},<br/>
            {"nom": "Bob", "temps": 47},<br/>
            {"nom": "Ana", "temps": 58}]</p>
<p>def cle(c):<br/>
    return -c["temps"]</p>
<p>classement = sorted(coureurs, key=cle)<br/>
print(classement[0]["nom"])<br/>
``<br/>
Qu'affiche ce programme ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>sorted range la table par valeurs croissantes de la fonction clé. Renvoyer l'opposé d'une colonne numérique inverse donc l'ordre : on obtient un tri décroissant sur cette colonne.</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>Rien, une clé de tri négative provoquant une erreur</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : une clé peut être n'importe quel nombre, négatif compris. sorted compare simplement les valeurs renvoyées par cle, sans erreur.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Lou</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : sorted renvoie une nouvelle liste réellement triée, l'ordre initial n'est pas conservé. Le premier élément est celui dont la clé est la plus petite.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Bob</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : ce serait le premier d'un tri par temps croissant. Ici la clé vaut -47 pour Bob, la plus grande des trois : Bob arrive en dernier.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Ana</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : les clés valent -52, -47 et -58. Le tri croissant place en tête la plus petite, -58, celle d'Ana : la table est rangée par temps décroissant.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Tables de données — Q19 : Exemple concret</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Lequel des fichiers Open Data suivants se prête<br/>
naturellement à une représentation en table ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Open Data : data.gouv.fr, opendata.paris.fr,<br/>
INSEE... regorgent de jeux de données en CSV<br/>
directement utilisables.</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 PDF illustré</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : un PDF est un format de<br/>
présentation, mal adapté à la manipulation<br/>
tabulaire (sauf après extraction).</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Une vidéo de présentation des différents transports urbains</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : un fichier multimédia ne se<br/>
structure pas en table.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Une carte des arrondissements de Paris au format SVG</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : SVG est un format vectoriel, pas<br/>
tabulaire.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>La liste des stations Vélib' au format CSV</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : un cas typique. Chaque ligne<br/>
= une station, descripteurs = nom,<br/>
longitude, latitude, capacité, etc. Idéal<br/>
pour traitement en table.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Tables de données — Q20 : Limite des tables</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Pour quel type de données les tables sont-elles<br/>
<strong>mal adaptées</strong> ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Règle générale : pour des données <strong>plates</strong>, la table est adaptée ; pour des données <strong>hiérarchiques</strong>, comme un arbre généalogique, une représentation où les données s'emboîtent, à la manière d'un arbre, est plus naturelle.</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 arbre généalogique avec des relations multiples</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : les relations<br/>
parent/enfant/conjoint sont <strong>hiérarchiques</strong>.<br/>
Les tables peuvent les stocker, mais ce n'est<br/>
pas la représentation la plus naturelle pour<br/>
ce type de données.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Une liste de produits avec prix</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Données plates : table parfaitement adaptée.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Une liste d'élèves avec nom, âge, ville</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Données plates : parfaitement adaptées à<br/>
une table.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Un classement sportif officiel regroupant plusieurs équipes</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Données plates : table adaptée.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Tables de données — Q21 : Trace d'accès</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Soit<br/>
`<code>python<br/>
t = [<br/>
    {"a": 1, "b": 2},<br/>
    {"a": 3, "b": 4},<br/>
    {"a": 5, "b": 6}<br/>
]<br/>
</code><br/>
Que vaut sum([l["a"] for l in t if l["b"] &gt;= 4])` ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Méthode : (1) appliquer le filtre l["b"] &gt;= 4<br/>
à chaque ligne ; (2) extraire l["a"] pour les<br/>
lignes restantes ; (3) sommer.</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>8</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : les lignes filtrées sont<br/>
{"a": 3, "b": 4} (b=4 ≥ 4) et {"a": 5, "b": 6} (b=6 ≥ 4). Somme des a :<br/>
3 + 5 = 8.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>1</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : tu as sommé les a des lignes rejetées,<br/>
{"a": 1, "b": 2}, dont le b est strictement inférieur à 4.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>9</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : tu as additionné les a de toutes<br/>
les lignes (1 + 3 + 5) sans filtrer.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>0</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : il y a bien des lignes qui<br/>
satisfont l["b"] &gt;= 4.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Tables de données — Q22 : Transformer la structure</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>On veut convertir la <strong>liste de dictionnaires</strong><br/>
`<code>python<br/>
table = [<br/>
    {"x": 1, "y": 2},<br/>
    {"x": 3, "y": 4}<br/>
]<br/>
</code><br/>
en <strong>dictionnaire de listes</strong> {"x": [1, 3], "y": [2, 4]}<br/>
(représentation « colonne par colonne »), rangé<br/>
dans colonnes`. Quel code est correct ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>La représentation colonne par colonne facilite les<br/>
calculs sur une colonne entière (somme, moyenne,<br/>
maximum de colonnes["x"]) sans reparcourir les<br/>
lignes. La transformation inverse (dictionnaire de<br/>
listes vers liste de dictionnaires) se fait de<br/>
façon symétrique.</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/>
colonnes = []<br/>
for k in table[0]:<br/>
    for l in table:<br/>
        colonnes.append(l[k])<br/>
</code>`</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : colonnes est une simple liste plate,<br/>
[1, 3, 2, 4] : les noms de colonnes sont<br/>
perdus. Il faut un dictionnaire dont chaque<br/>
valeur est la liste d'une colonne.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>`<code>python<br/>
colonnes = {}<br/>
for k in table[0]:<br/>
    colonnes[k] = [l[k] for l in table]<br/>
</code>`</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : pour chaque clé du premier<br/>
dictionnaire (les descripteurs), on construit<br/>
la liste des valeurs de cette clé sur toutes<br/>
les lignes.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>`<code>python<br/>
colonnes = {}<br/>
for l in table:<br/>
    for k in l:<br/>
        colonnes[k] = l[k]<br/>
</code>`</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : on range une <strong>valeur</strong> et non une<br/>
liste, écrasée à chaque ligne. On obtient<br/>
{"x": 3, "y": 4} : seule la dernière ligne<br/>
subsiste.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>`<code>python<br/>
colonnes = {}<br/>
for k in table:<br/>
    colonnes[k] = [l[k] for l in table]<br/>
</code>`</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : for k in table parcourt les<br/>
<strong>lignes</strong> (des dictionnaires), pas les clés.<br/>
l[k] avec k dictionnaire lève TypeError<br/>
(un dictionnaire ne peut pas servir de clé).<br/>
Il faut prendre les clés d'une ligne, par<br/>
exemple table[0].</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Tables de données — Q23 : Performance d'une jointure</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Pour une jointure entre deux tables de tailles<br/>
n et m, la version naïve à deux boucles<br/>
imbriquées a une complexité de O(n × m). Comment<br/>
l'améliorer ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>L'idée est de remplacer la recherche par parcours de toute une table par un accès direct à la ligne voulue grâce à sa clé : chaque table n'est alors parcourue qu'une seule fois.</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>En représentant chaque ligne par un tuple plutôt que par un dictionnaire</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : changer la représentation d'une ligne<br/>
ne change pas le nombre de comparaisons, les<br/>
deux boucles imbriquées font toujours n × m<br/>
tours. Ce n'est pas une optimisation<br/>
algorithmique.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>En triant d'abord les deux tables, tout en gardant les deux boucles imbriquées</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : trier ne sert à rien si l'on garde ensuite les deux boucles imbriquées, qui font toujours n × m comparaisons. Un tri n'accélère une jointure que si l'algorithme en tire parti, par un parcours simultané des deux tables triées, et le tri a lui-même un coût.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>En indexant l'une des deux tables par sa clé dans un dictionnaire</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : l'accès à un dictionnaire par<br/>
sa clé est en O(1). On construit l'index en un<br/>
seul parcours, avec idx[e["id"]] = e pour<br/>
chaque élève e, puis chaque note n ne<br/>
coûte qu'un accès : e = idx[n["id_eleve"]].<br/>
La jointure passe de O(n × m) à O(n + m),<br/>
beaucoup plus rapide pour de gros volumes.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>En ne conservant que les colonnes utiles dans chacune des deux tables</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : la complexité dépend du <strong>nombre de<br/>
lignes</strong> parcourues, pas du nombre de colonnes.<br/>
Chaque ligne est plus légère, mais les deux<br/>
boucles imbriquées font toujours n × m<br/>
comparaisons.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Tables de données — Q24 : Une sélection qui s'arrête trop tôt</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Un élève écrit une fonction qui renvoie les noms des élèves d'une classe :<br/>
``python<br/>
def eleves_de(table, classe):<br/>
    resultat = []<br/>
    for l in table:<br/>
        if l["classe"] == classe:<br/>
            resultat.append(l["nom"])<br/>
        return resultat</p>
<p>t = [{"nom": "Ana", "classe": "1A"},<br/>
     {"nom": "Bob", "classe": "1B"},<br/>
     {"nom": "Eva", "classe": "1B"}]<br/>
print(eleves_de(t, "1B"))<br/>
``<br/>
Qu'affiche ce programme ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Dans une sélection de lignes, la table doit être parcourue en entier avant de renvoyer le résultat : le return se place après la boucle. Une indentation de trop suffit à arrêter la fonction dès la première ligne.</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>None</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : la fonction atteint bien un return, celui de la boucle, qui renvoie la liste resultat telle qu'elle est à ce moment, c'est-à-dire vide.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>['Bob']</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : tu fais arrêter la fonction à la première ligne retenue, mais le return ne dépend pas du test : il est atteint dès la ligne d'Ana, avant que Bob ne soit examiné.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>[]</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : au premier tour, Ana n'est pas en 1B, rien n'est ajouté, puis return resultat renvoie la liste vide. Bob et Eva ne sont jamais examinés. Il faut désindenter le return au niveau du for.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>['Bob', 'Eva']</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : ce serait le cas si return resultat était placé après la boucle. Indenté dans la boucle, il s'exécute dès le premier tour.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Tables de données — Q25 : Synthèse</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Parmi les affirmations suivantes sur les tables de<br/>
données, laquelle est <strong>fausse</strong> ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Les tables de données et leurs opérations<br/>
associées (recherche, tri, fusion) sont au cœur<br/>
du traitement de données. Les maîtriser en<br/>
Python est un atout majeur pour<br/>
manipuler de gros volumes.</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>En Python, on représente couramment une table par une liste de dictionnaires</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Vrai : c'est la représentation la plus<br/>
fréquente en NSI Première.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Les opérations classiques sont la recherche, le tri, la sélection de lignes (filtrage), la sélection de colonnes et la fusion</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Vrai : ce sont les opérations canoniques sur<br/>
les tables, prévues par le programme.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Une fusion permet de combiner deux tables sur la base d'un descripteur commun</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Vrai : c'est exactement le rôle de la fusion,<br/>
qui rapproche les lignes de deux tables<br/>
partageant une clé.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Le module csv produit toujours des données typées (entiers, flottants, dates)</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Faux (donc bonne réponse) : csv produit<br/>
uniquement des <strong>chaînes</strong>. C'est au<br/>
programme de convertir les types.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Tables de données — Q26 : La clé d'une fusion</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>La table eleves a pour descripteurs id, nom et classe ; la<br/>
table notes a pour descripteurs id_eleve, matiere et note.<br/>
Sur quelle égalité repose la fusion des deux tables ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Fusionner deux tables exige une colonne dont les valeurs se<br/>
correspondent, en général un identifiant.</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>e["classe"] == n["note"]</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : une classe et une note ne sont pas comparables.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>e["id"] == n["id_eleve"]</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : l'identifiant de l'élève figure dans les deux<br/>
tables, sous deux noms de colonnes différents. C'est lui qui<br/>
relie une note à un élève.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>e["nom"] == n["matiere"]</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : un nom d'élève et une matière n'ont rien à voir.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>e["id"] == n["note"]</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : un identifiant et une note ne se correspondent pas ;<br/>
on compare la colonne commune aux deux tables.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Tables de données — Q27 : Le nombre de lignes d'une fusion</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>La table eleves contient deux lignes, d'identifiants 1 et 2.<br/>
La table notes contient des lignes dont les id_eleve sont<br/>
1, 1 et 2. Combien de lignes contient resultat ?<br/>
`<code>python<br/>
resultat = []<br/>
for e in eleves:<br/>
    for n in notes:<br/>
        if e["id"] == n["id_eleve"]:<br/>
            resultat.append({"nom": e["nom"], "note": n["note"]})<br/>
</code>`</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Une fusion produit une ligne par couple de lignes qui se<br/>
correspondent : 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>2 lignes, une par élève</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : un élève ayant plusieurs notes apparaît plusieurs fois,<br/>
et un élève sans note n'apparaît pas.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>1 ligne</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : chaque correspondance ajoute une ligne, et il y en a<br/>
plusieurs.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>3 lignes</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : chaque note est associée à l'élève dont<br/>
l'identifiant correspond, soit deux notes pour l'élève 1 et une pour l'élève 2. Une ligne par<br/>
correspondance trouvée.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>6 lignes, une par couple de la double boucle</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : seuls les couples dont les identifiants coïncident sont<br/>
ajoutés.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Tables de données — Q28 : Un élève sans note</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Dans la fusion des tables eleves et notes par identifiant, un<br/>
élève n'a encore aucune note. Que devient-il dans la table<br/>
fusionnée ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Avant d'exploiter une fusion, il faut savoir quelles lignes ont pu<br/>
disparaître faute de correspondance.</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>Il y figure avec une note vide, ajoutée automatiquement</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : ce serait un autre traitement, à programmer<br/>
explicitement ; la fusion simple ne complète rien.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>La fusion échoue avec une erreur de clé absente</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : l'absence de correspondance ne provoque aucune erreur,<br/>
seulement une ligne absente.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Il y figure avec la note 0, valeur par défaut</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : aucune valeur n'est inventée par la fusion.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Il n'y figure pas, faute de correspondance</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : la fusion ne produit une ligne que lorsqu'une<br/>
correspondance existe. Sans note, aucune ligne n'est créée pour<br/>
lui.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Tables de données — Q29 : Une colonne calculée</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>La table table contient, pour chaque élève, les descripteurs<br/>
nom, n1 et n2, deux notes lues comme chaînes. Que fait ce<br/>
programme ?<br/>
`<code>python<br/>
for ligne in table:<br/>
    ligne["moyenne"] = (int(ligne["n1"]) + int(ligne["n2"])) / 2<br/>
</code>`</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Ajouter une colonne calculée transforme la table sans la recréer :<br/>
chaque ligne reçoit une clé de plus.</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>Il remplace n1 et n2 par leur moyenne dans chaque ligne</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : n1 et n2 ne sont pas modifiées ; une clé<br/>
supplémentaire est créée.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Il crée une nouvelle table sans toucher à table</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : les dictionnaires de table sont modifiés sur place.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Il ajoute à chaque ligne un descripteur moyenne</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : affecter une nouvelle clé dans chaque<br/>
dictionnaire ajoute une colonne à la table, remplie ligne par<br/>
ligne.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Il échoue, une clé absente ne pouvant être affectée</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : affecter une clé absente est précisément la façon<br/>
d'ajouter une entrée à un dictionnaire.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Tables de données — Q30 : Indexer une table par identifiant</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Avant de fusionner deux grandes tables, Nora construit :<br/>
`<code>python<br/>
index = {}<br/>
for e in eleves:<br/>
    index[e["id"]] = e<br/>
</code>`<br/>
Quel est l'intérêt de ce dictionnaire ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Indexer une table par une clé transforme une recherche linéaire en<br/>
accès direct : c'est ce qui rend une fusion rapide sur de grandes<br/>
tables.</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>Supprimer les élèves en double dans la table</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : si deux élèves avaient le même identifiant, l'un<br/>
écraserait l'autre, mais ce n'est pas le but.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Réduire la mémoire occupée par la table des élèves</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : l'index s'ajoute à la table, il ne la remplace pas.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Retrouver un élève par identifiant sans parcours</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : index[n["id_eleve"]] donne directement la<br/>
ligne cherchée. La fusion ne parcourt plus qu'une table au lieu<br/>
d'imbriquer deux boucles.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Trier les élèves par identifiant croissant</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : un dictionnaire n'est pas un tri ; il sert à accéder<br/>
directement.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Tables de données — Q31 : Combien de lignes sont retenues</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Les âges de la table sont, dans l'ordre, "15", "17", "16" et<br/>
"18". Combien de lignes la sélection suivante garde-t-elle ?<br/>
`<code>python<br/>
majeurs = []<br/>
for ligne in table:<br/>
    if int(ligne["age"]) &gt;= 17:<br/>
        majeurs.append(ligne)<br/>
</code>`</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Sélectionner des lignes, c'est garder celles qui vérifient une<br/>
condition, après conversion des valeurs textuelles.</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>0</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : au moins un âge atteint 17.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>2</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : la condition &gt;= 17 est vraie pour 2 des<br/>
quatre âges.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>4</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : la condition écarte les âges inférieurs à 17.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Une erreur, un âge ne pouvant être comparé à un entier</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : int convertit l'âge avant la comparaison.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Tables de données — Q32 : Un tri décroissant</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Que change l'argument reverse=True dans<br/>
sorted(table, key=cle, reverse=True) ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>sorted combine une clé, qui dit sur quoi trier, et reverse,<br/>
qui dit dans quel sens.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Les lignes vont de la plus grande clé à la plus petite</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : le tri reste fondé sur cle, mais l'ordre est<br/>
inversé, du plus grand au plus petit.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Les lignes sont inversées sans être triées par la clé</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : reverse s'applique au tri, pas à l'ordre initial.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>La fonction cle est appliquée aux lignes dans l'ordre inverse</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : cle est appelée normalement sur chaque ligne.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>La table d'origine est modifiée et inversée</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : sorted renvoie une nouvelle liste et laisse table<br/>
intacte.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Tables de données — Q33 : La meilleure note de la table</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Les notes de la table sont, dans l'ordre, "12", "18", "15". Qu'affiche ce<br/>
programme ?<br/>
`<code>python<br/>
maxi = 0<br/>
for ligne in table:<br/>
    if int(ligne["note"]) &gt; maxi:<br/>
        maxi = int(ligne["note"])<br/>
print(maxi)<br/>
</code>`</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Chercher un maximum dans une table suit le schéma de la recherche<br/>
de maximum dans une liste, avec une conversion des valeurs.</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>0</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : maxi est mis à jour dès la première note, supérieure<br/>
à 0.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>12</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : 12 est une note intermédiaire, remplacée dès qu'une<br/>
note plus grande apparaît.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>18</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : maxi est remplacé à chaque note strictement<br/>
supérieure ; il finit par contenir la plus grande.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>15</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : 15 n'est pas la plus grande note ; relis le parcours.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Tables de données — Q34 : Trier par classe puis par nom</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Lina veut une table triée par classe, et, à l'intérieur de chaque<br/>
classe, par nom. sorted conserve l'ordre relatif des lignes de<br/>
même clé. Dans quel ordre doit-elle enchaîner les deux tris ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Avec un tri qui conserve l'ordre des égaux, on trie du critère<br/>
secondaire au critère principal.</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 seul tri par classe suffit</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : les noms resteraient dans leur ordre d'origine à<br/>
l'intérieur de chaque classe.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>D'abord par classe, puis par nom</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : le tri par nom mélangerait les classes.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>L'ordre des deux tris n'a pas d'importance</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : c'est le dernier tri qui domine ; il doit porter sur le<br/>
critère principal.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>D'abord par nom, puis par classe</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : le second tri regroupe les classes sans<br/>
défaire l'ordre des noms à l'intérieur de chacune, puisque les<br/>
lignes de même classe gardent leur ordre relatif.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Tables de données — Q35 : Un descripteur absent</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>La table a pour descripteurs nom, age et ville. Que produit<br/>
ligne["taille"] pour une ligne de cette table ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Les descripteurs d'une table sont fixés par son en-tête ; tout<br/>
accès doit employer exactement ces noms.</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 chaîne vide, valeur par défaut d'un dictionnaire</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : Python ne renvoie pas de valeur par défaut pour une<br/>
clé absente.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>La valeur de la colonne la plus proche, ville</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : les clés sont exactes, il n'y a aucune approximation.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Une erreur, la clé taille n'existant pas</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : accéder à une clé absente d'un dictionnaire lève<br/>
une KeyError. Les descripteurs disponibles sont ceux de<br/>
l'en-tête.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>None, l'absence de valeur</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : l'accès par crochets échoue au lieu de renvoyer<br/>
None.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Tables de données — Q36 : Des lignes aux mêmes descripteurs</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Pourquoi exige-t-on que toutes les lignes d'une table aient<br/>
exactement les mêmes descripteurs ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Une table est une collection homogène : mêmes descripteurs pour<br/>
toutes les lignes, ce qui rend les opérations prévisibles.</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 que le fichier CSV soit plus court</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : la taille du fichier n'est pas en cause.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Parce que Python refuse des dictionnaires de clés différentes dans une liste</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : Python l'accepte ; c'est le traitement des données qui<br/>
l'exige.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Pour qu'un même traitement s'applique à chaque ligne sans vérification</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : trier par age, filtrer par ville ou calculer<br/>
une moyenne suppose que chaque ligne possède ces clés. Une ligne<br/>
différente ferait échouer le traitement.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Pour pouvoir trier la table par n'importe quelle colonne du fichier</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : le tri est un cas particulier ; la raison est plus<br/>
générale, l'uniformité de tous les traitements.</p>]]></text>
    </feedback>
  </answer>
</question>

</quiz>
