<?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<br/>
plus répandue pour organiser des données : tableurs,<br/>
bases relationnelles, fichiers CSV, DataFrames pandas<br/>
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="0" format="html">
    <text><![CDATA[<p>Un meuble pour poser un ordinateur</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Plaisanterie : on parle bien d'une structure<br/>
informatique, pas de mobilier.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Un type primitif de 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>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Un tableau composé de lignes (enregistrements) et de colonnes (descripteurs ou attributs)</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>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>
</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 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="0" format="html">
    <text><![CDATA[<p>Une clé primaire</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : une clé primaire est un <strong>descripteur<br/>
particulier</strong> qui identifie de manière unique<br/>
chaque ligne. Toutes les colonnes ne sont pas<br/>
des clés primaires.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Un enregistrement</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : un enregistrement est une <strong>ligne</strong>,<br/>
pas une colonne.</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>
</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 simple chaîne de caractères</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="100" format="html">
    <text><![CDATA[<p>Comme une liste de dictionnaires, chaque dictionnaire représentant une ligne</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : exemple<br/>
<code>[{"nom":"Alice","age":17}, {"nom":"Bob","age":16}]</code>.<br/>
C'est ce que renvoie <code>csv.DictReader</code> quand on<br/>
le convertit en liste. Très lisible<br/>
(<code>ligne["nom"]</code>).</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>
  <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>
</question>

<question type="multichoice">
  <name>
    <text>Tables de données — Q04 : Accéder à une cellule</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Soit <code>table = [{"nom":"Alice","age":17}, {"nom":"Bob","age":16}]</code>.<br/>
Comment accéder à l'âge de Bob ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Schéma général : <code>table[indice_ligne][descripteur]</code>.<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="100" format="html">
    <text><![CDATA[<p><code>table[1]['age']</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : Bob est la deuxième ligne<br/>
(indice 1), et <code>'age'</code> est le descripteur. On<br/>
obtient <code>16</code>.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p><code>table['Bob']['age']</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : <code>table</code> est une <strong>liste</strong>, pas un<br/>
dictionnaire indexé par nom. Cela lève<br/>
<code>TypeError</code>.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p><code>table[2]['age']</code></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.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p><code>table.age[1]</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : aucune méthode ni attribut <code>.age</code> sur<br/>
une liste.</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é <code>"nom"</code>), 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[<pre><code>print(table.nom)</code></pre>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : pas d'attribut <code>.nom</code> sur une liste.<br/>
Cela lève <code>AttributeError</code>.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<pre><code>for ligne in table:
    print(ligne["nom"])</code></pre>]]></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é <code>"nom"</code>.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<pre><code>for nom in table:
    print(nom)</code></pre>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : la variable <code>nom</code> recevrait chaque<br/>
<strong>dictionnaire</strong> entier, pas le nom seulement.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<pre><code>print(table["nom"])</code></pre>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : <code>table</code> est une liste, on ne peut<br/>
pas indexer par chaîne.</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é du NSI : savoir lire des<br/>
données réelles (souvent en CSV ou JSON), les<br/>
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="100" format="html">
    <text><![CDATA[<p>D'un fichier (CSV, JSON), d'un tableur, d'une base de données, d'une API web...</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : les tables sont partout en<br/>
informatique. Open Data (data.gouv.fr),<br/>
extracts SQL, exports Excel, scraping web...<br/>
autant de sources possibles.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Aucune des réponses précédentes</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : la deuxième proposition est<br/>
correcte.</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="0" format="html">
    <text><![CDATA[<p>Uniquement d'une base de données SQL</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Trop restrictif : SQL est une source<br/>
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="0" format="html">
    <text><![CDATA[<pre><code>for ligne in table:
    if ligne["age"] &gt; 16:
        print(ligne)</code></pre>]]></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>
  <answer fraction="100" format="html">
    <text><![CDATA[<pre><code>[ligne for ligne in table if ligne["age"] &gt; 16]</code></pre>]]></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[<pre><code>table.find(age &gt; 16)</code></pre>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : la méthode <code>.find()</code> n'existe pas<br/>
sur les listes.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<pre><code>table[ligne["age"] &gt; 16]</code></pre>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : syntaxe invalide. <code>ligne</code> n'est pas<br/>
défini hors d'une boucle.</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 <code>with</code>, 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>Possible mais fastidieux et fragile. Il existe<br/>
un outil dédié.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p><code>csv.load('data.csv')</code> (cette fonction existe-t-elle ?)</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Non, cette fonction n'existe pas dans le<br/>
module <code>csv</code>.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p><code>list(csv.DictReader(open('data.csv', encoding='utf-8')))</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : <code>csv.DictReader</code> produit un<br/>
itérateur de dictionnaires ; <code>list()</code> le<br/>
matérialise en table prête à l'emploi.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p><code>json.load(open('data.csv'))</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : <code>json.load</code> lit du JSON, pas du CSV.</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/>
<code>len(table[0])</code> (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="0" format="html">
    <text><![CDATA[<p><code>size(table)</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : pas de fonction <code>size</code> en Python<br/>
standard.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p><code>len(table.keys())</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : <code>.keys()</code> n'existe pas sur une<br/>
liste. Cela lève <code>AttributeError</code>.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p><code>len(table)</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : <code>len()</code> sur la liste donne le<br/>
nombre de dictionnaires, donc de lignes.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p><code>table.count</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : <code>.count</code> est une <strong>méthode</strong> (qui<br/>
compte les occurrences d'un élément), il faut<br/>
l'appeler avec des parenthèses et un<br/>
argument.</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 <code>len(table)</code> 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 : <code>moyenne = total / len(table)</code> lèverait<br/>
<code>ZeroDivisionError</code>.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Une exception est levée</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : <code>len([])</code> renvoie <code>0</code> sans erreur.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p><code>0</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : <code>[]</code> (liste vide) contient<br/>
zéro élément.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p><code>-1</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : <code>len</code> n'est jamais négatif.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p><code>None</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : <code>len</code> renvoie toujours un entier.</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>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/>
<code>sorted(table, key=lambda r: r['age'])</code>. Pour un<br/>
tri <strong>décroissant</strong>, ajouter <code>reverse=True</code>.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="100" format="html">
    <text><![CDATA[<p><code>table.sort(key=lambda ligne: ligne['age'])</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : <code>key</code> indique sur quoi<br/>
comparer. La lambda renvoie l'âge de chaque<br/>
ligne. Tri en place de la liste.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p><code>table.sort()</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : <code>sort</code> ne sait pas comparer deux<br/>
dictionnaires sans préciser sur quel<br/>
descripteur.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p><code>sorted(table, by='age')</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : <code>sorted</code> n'a pas d'argument <code>by</code>.<br/>
C'est <code>key=</code> qu'il faut.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p><code>table.sort('age')</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : <code>sort</code> n'accepte pas une chaîne<br/>
comme premier argument positionnel. Il faut<br/>
le mot-clé <code>key=</code>.</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 ne contenant<br/>
que les colonnes <code>nom</code> et <code>age</code> (sans les autres<br/>
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. C'est<br/>
l'une des manipulations classiques de tables,<br/>
au même titre que la sélection de lignes, le<br/>
tri ou la fusion.</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>table[['nom', 'age']]</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : c'est une syntaxe <strong>pandas</strong>, pas<br/>
Python standard.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p><code>table.select('nom', 'age')</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : la méthode <code>.select</code> n'existe pas<br/>
sur les listes (cela ressemble à du SQL).</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p><code>[{k: l[k] for k in ['nom', 'age']} for l in table]</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : compréhension de liste<br/>
imbriquée avec une compréhension de<br/>
dictionnaire. Pour chaque ligne, on<br/>
reconstruit un dictionnaire ne gardant que les<br/>
clés voulues.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p><code>table.keep('nom', 'age')</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : pas de méthode <code>.keep</code> en Python<br/>
standard.</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 <code>t1</code> et <code>t2</code> ayant les <strong>mêmes<br/>
descripteurs</strong>. Comment obtenir une nouvelle table<br/>
contenant toutes les lignes de <code>t1</code> puis celles de<br/>
<code>t2</code> ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Pour modifier <code>t1</code> <strong>en place</strong> au lieu de créer<br/>
une nouvelle table : <code>t1.extend(t2)</code> ou<br/>
<code>t1 += t2</code>.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p><code>t1.append(t2)</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Attention : <code>append(t2)</code> ajouterait <code>t2</code><br/>
comme <strong>un seul élément</strong> (une liste de<br/>
listes), pas en fusionnant. Il faudrait<br/>
plutôt <code>extend</code>.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p><code>fusion(t1, t2)</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : pas de fonction <code>fusion</code> en Python<br/>
standard.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p><code>t1.merge(t2)</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : pas de méthode <code>.merge</code> sur les<br/>
listes (cela ressemble à du pandas).</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p><code>t1 + t2</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : la concaténation de listes<br/>
(<code>+</code>) 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 <code>age</code> (entier) ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Penser à gérer le cas de la table <strong>vide</strong><br/>
(division par zéro) : tester <code>if table:</code> avant<br/>
le calcul, ou utiliser<br/>
<code>sum(...) / len(table) if table else 0</code>.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p><code>mean(table.age)</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : pas de fonction <code>mean</code> en standard,<br/>
et pas d'attribut <code>.age</code> sur une liste.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p><code>table.average('age')</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : pas de méthode <code>.average</code>.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p><code>sum(table['age']) / len(table)</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : <code>table</code> est une <strong>liste</strong>, on ne<br/>
peut pas l'indexer par chaîne. Lève<br/>
<code>TypeError</code>.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p><code>sum(ligne['age'] for ligne in table) / len(table)</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : on extrait la valeur <code>age</code><br/>
pour chaque ligne via une expression<br/>
génératrice, puis on divise par le nombre de<br/>
lignes.</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 <code>eleves = [{"id":1,"nom":"Alice"},...]</code> et<br/>
<code>notes = [{"id_eleve":1,"matiere":"Maths","note":15},...]</code>.<br/>
Pour associer chaque note au nom de l'élève, on<br/>
effectue une <strong>jointure</strong>. Quel pseudo-code<br/>
l'implémente 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 <code>eleves</code> par <code>id</code> 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[<pre><code>notes + eleves</code></pre>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : la concaténation ne fait aucune<br/>
mise en correspondance.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<pre><code>eleves.merge(notes)</code></pre>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : pas de méthode <code>.merge</code> en Python<br/>
standard.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<pre><code>for n in notes:
    for e in eleves:
        if n["id_eleve"] == e["id"]:
            print(e["nom"], n["matiere"], n["note"])</code></pre>]]></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. Complexité O(n × m).</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<pre><code>for n in notes:
    print(eleves[n["id_eleve"]]["nom"])</code></pre>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : <code>eleves[1]</code> accède à l'<strong>indice 1</strong><br/>
de la liste, pas à l'élève d'<code>id</code> 1.<br/>
Coïncidence possible mais code incorrect en<br/>
général.</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 <code>csv.DictReader</code>, 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>Le module <code>csv</code> 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>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="0" format="html">
    <text><![CDATA[<p>Il faut payer une licence pour utiliser <code>csv.DictReader</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : le module <code>csv</code> est gratuit et inclus<br/>
dans Python standard.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Oublier de convertir les valeurs en <code>int</code> (les valeurs lues sont des chaînes)</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : <code>csv.DictReader</code> ne fait<br/>
aucune conversion de type. <code>"17" + "16"</code><br/>
donne <code>"1716"</code>, pas <code>33</code>. Toujours convertir<br/>
avant de calculer.</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>Comment compter le nombre d'élèves dans chaque<br/>
ville à partir de <code>table = [{"nom":..., "ville":...}, ...]</code> ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Alternative plus concise avec<br/>
<code>collections.Counter</code> :<br/>
<code>Counter(ligne["ville"] for ligne in table)</code>.<br/>
Mais le schéma manuel est universel.</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>set(table['ville'])</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : <code>table</code> est une liste, on ne peut<br/>
pas l'indexer par chaîne.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<pre><code>c = {}
for ligne in table:
    v = ligne["ville"]
    c[v] = c.get(v, 0) + 1</code></pre>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : on construit progressivement<br/>
un dictionnaire <code>ville → effectif</code>. La<br/>
méthode <code>.get(v, 0)</code> renvoie <code>0</code> si la ville<br/>
n'a pas encore été rencontrée.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p><code>len(table)</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : cela donne le total, pas la<br/>
répartition par ville.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p><code>table.count('ville')</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : <code>count</code> cherche un élément exact<br/>
dans la liste, pas un comptage par<br/>
catégorie.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Tables de données — Q18 : Tri sur deux critères</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Comment trier la table par <strong>âge croissant</strong>, puis<br/>
par <strong>nom alphabétique</strong> en cas d'égalité ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Astuce élégante : la comparaison des tuples<br/>
Python est lexicographique, ce qui simplifie<br/>
beaucoup les tris multi-critères.</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>table.sort(key=lambda l: (l['age'], l['nom']))</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : la clé est un <strong>tuple</strong>.<br/>
Python compare lexicographiquement les<br/>
tuples : d'abord par âge, puis par nom en<br/>
cas d'égalité.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p><code>table.sort('age', 'nom')</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : <code>sort</code> n'accepte pas plusieurs<br/>
arguments positionnels.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p><code>table.sort(key=lambda l: l['age'] + l['nom'])</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : on ne peut pas additionner un entier<br/>
et une chaîne. Et ce ne serait pas<br/>
sémantiquement correct.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p><code>table.sort(by=['age', 'nom'])</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : c'est la syntaxe pandas, pas Python<br/>
standard.</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="100" format="html">
    <text><![CDATA[<p>La liste des stations Vélib' avec leurs coordonnées et capacités, 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>
  <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="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 transports</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : un fichier multimédia ne se<br/>
structure pas 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<br/>
table est adaptée ; pour des données <strong>hiérarchiques</strong><br/>
(comme un arbre généalogique), un format imbriqué<br/>
(JSON par exemple) est plus naturel.</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 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>Un classement sportif</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Données plates : table adaptée.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Un arbre généalogique sur plusieurs générations 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 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>
</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/>
<pre><code>t = [{"a":1,"b":2}, {"a":3,"b":4}, {"a":5,"b":6}]</code></pre><br/>
Que vaut <code>sum(l["a"] for l in t if l["b"] &gt;= 4)</code> ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Méthode : (1) appliquer le filtre <code>l["b"] &gt;= 4</code><br/>
à chaque ligne ; (2) extraire <code>l["a"]</code> 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="0" format="html">
    <text><![CDATA[<p>12</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : tu as additionné les <code>a</code> de toutes<br/>
les lignes (1 + 3 + 5) sans filtrer.</p>]]></text>
    </feedback>
  </answer>
  <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/>
<code>{"a":3,"b":4}</code> (b=4 ≥ 4) et <code>{"a":5,"b":6}</code><br/>
(b=6 ≥ 4). Somme des <code>a</code> : 3 + 5 = 8.</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 <code>l["b"] &gt;= 4</code>.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>9</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : tu as inclus la première ligne<br/>
(a=1) à tort. Or <code>b=2</code>, donc le filtre rejette.</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 une <strong>liste de dictionnaires</strong><br/>
<code>[{"x":1,"y":2}, {"x":3,"y":4}]</code> en <strong>dictionnaire<br/>
de listes</strong> <code>{"x":[1,3], "y":[2,4]}</code> (représentation<br/>
"colonne par colonne"). Quel code est correct ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Cette transformation est très utile pour passer<br/>
à <code>numpy</code>/<code>matplotlib</code>, qui préfèrent souvent les<br/>
colonnes individuelles aux listes<br/>
d'enregistrements.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="100" format="html">
    <text><![CDATA[<pre><code>{k: [l[k] for l in table] for k in table[0]}</code></pre>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : compréhension de<br/>
dictionnaire. Pour chaque clé du premier<br/>
dictionnaire, on construit la liste des<br/>
valeurs de cette clé sur toutes les lignes.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p><code>table.pivot()</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : pas de méthode <code>.pivot</code> en Python<br/>
standard (cela existe en pandas).</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<pre><code>{k: l[k] for l in table for k in l}</code></pre>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : on écrase les valeurs à chaque<br/>
itération (chaque clé n'aura que la dernière<br/>
valeur).</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p><code>dict(table)</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : <code>dict</code> ne sait pas faire cette<br/>
transformation. Lèverait <code>TypeError</code> ou<br/>
produirait un résultat inattendu.</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/>
<code>n</code> et <code>m</code>, 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>C'est exactement ce que font les SGBD avec leurs<br/>
<strong>index</strong> : transformer une recherche linéaire<br/>
en accès direct quasi instantané (table de<br/>
hachage ou arbre B).</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 supprimant la moitié des colonnes</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : la complexité dépend du <strong>nombre de<br/>
lignes</strong>, pas du nombre de colonnes.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>En triant les deux tables au préalable</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Possible (jointure par fusion) mais coûteux<br/>
en pré-traitement. Il existe plus simple<br/>
en Python.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>En indexant une table par sa clé dans un dictionnaire (accès O(1)), ce qui ramène la jointure à O(n + m)</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : par exemple,<br/>
<code>idx = {e["id"]: e for e in eleves}</code>, puis<br/>
<code>for n in notes: e = idx.get(n["id_eleve"])</code>.<br/>
Beaucoup plus rapide pour de gros volumes.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>En utilisant des tuples au lieu de dictionnaires</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Pas une vraie optimisation algorithmique.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Tables de données — Q24 : Bug subtil</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Un élève écrit<br/>
<pre><code>for ligne in table:
    if ligne["age"] &gt; 16:
        table.remove(ligne)</code></pre><br/>
Quel est le problème ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Bonne pratique : <strong>ne jamais modifier</strong> une<br/>
structure pendant qu'on la parcourt. Construire<br/>
une nouvelle liste filtrée :<br/>
<code>table = [l for l in table if l["age"] &lt;= 16]</code>.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>La boucle ne compile pas</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : la syntaxe est valide, le code<br/>
s'exécute (mais avec un bug logique).</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Cela lève toujours une exception</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Pas toujours : ça produit un résultat<br/>
incorrect, sans erreur visible.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Modifier une liste pendant qu'on la parcourt provoque des lignes ignorées : certains éléments ne seront jamais testés</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : c'est un piège classique.<br/>
Quand on supprime l'élément d'indice <code>i</code>,<br/>
les indices suivants se décalent et le<br/>
parcours saute le suivant. Solution :<br/>
construire une nouvelle liste filtrée.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>La méthode <code>.remove</code> n'existe pas</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : elle existe parfaitement.</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>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="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="100" format="html">
    <text><![CDATA[<p>Le module <code>csv</code> produit toujours des données typées (entiers, flottants, dates)</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Faux (donc bonne réponse) : <code>csv</code> produit<br/>
uniquement des <strong>chaînes</strong>. C'est au<br/>
programme de convertir les types.</p>]]></text>
    </feedback>
  </answer>
</question>

</quiz>
