<?xml version="1.0" encoding="UTF-8"?>
<quiz>
<question type="category">
  <category>
    <text>$course$/QCM de NSI/Terminale/Programmation fonctionnelle</text>
  </category>
  <info format="html">
    <text><![CDATA[<p>Paradigme fonctionnel, fonctions pures, immuabilité, fonctions<br/>
de première classe et d'ordre supérieur (map, filter, reduce),<br/>
expressions lambda, récursivité, comparaison avec le paradigme<br/>
impératif.</p>]]></text>
  </info>
</question>

<question type="multichoice">
  <name>
    <text>Programmation fonctionnelle — Q01 : Paradigme fonctionnel</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Quelle est l'idée centrale du <strong>paradigme fonctionnel</strong> ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Origines : le lambda-calcul de Church (1936) et le<br/>
langage Lisp (1958). Aujourd'hui, des langages<br/>
purement fonctionnels (Haskell, OCaml) coexistent avec<br/>
des langages multi-paradigmes (Python, JavaScript).</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>Programmer en composant des fonctions, en évitant les modifications d'état (effets de bord)</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : la programmation fonctionnelle<br/>
privilégie les fonctions sans effet de bord<br/>
(« fonctions pures »), l'immutabilité des données et<br/>
la composition de fonctions. Cela rend le code plus<br/>
prévisible et plus facile à raisonner.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Programmer uniquement avec des boucles for</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : la programmation fonctionnelle remplace<br/>
plutôt les boucles par de la récursivité ou des<br/>
fonctions d'ordre supérieur.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Programmer en suivant l'ordre exact des instructions ligne par ligne</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : c'est le paradigme <strong>impératif</strong>, dont la<br/>
programmation fonctionnelle est précisément une<br/>
alternative.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Programmer en utilisant uniquement des objets et des classes</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : c'est le paradigme <strong>orienté objet</strong>, pas<br/>
fonctionnel.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Programmation fonctionnelle — Q02 : Fonction pure</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Qu'est-ce qu'une <strong>fonction pure</strong> ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Fonction pure typique : def carre(x): return x * x.<br/>
Fonction <strong>impure</strong> : def ajoute_a_liste(L, x): L.append(x)<br/>
modifie son argument, ce qui est un effet de bord.</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>Une fonction qui, pour les mêmes arguments, retourne toujours le même résultat et n'a aucun effet de bord (modification de variable globale, écriture dans un fichier, etc.)</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : la pureté implique la prévisibilité<br/>
totale et la facilité de test. C'est aussi ce qui<br/>
permet la mémoïsation transparente.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Une fonction qui modifie ses arguments</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : c'est l'inverse d'une fonction pure. Modifier<br/>
ses arguments est un effet de bord, ce qui rend la<br/>
fonction impure.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Une fonction écrite uniquement en Python</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : la pureté est indépendante du langage.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Une fonction qui ne contient aucun bug</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : « pure » est un terme technique précis,<br/>
pas un jugement de qualité.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Programmation fonctionnelle — Q03 : Immutabilité</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Que signifie qu'une donnée est <strong>immuable</strong> ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>L'immutabilité a plusieurs avantages : pas de<br/>
modifications inattendues, partage sûr entre threads,<br/>
possibilité de cacher les valeurs (les chaînes de<br/>
caractères en Python sont parfois cachées en interne).</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Elle est stockée sur le disque dur</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : aucun rapport avec le stockage.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Elle est protégée par un mot de passe</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : aucun rapport avec la sécurité. C'est une<br/>
propriété structurelle de la donnée.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Elle ne peut pas être modifiée après sa création</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : pour modifier, on crée une nouvelle<br/>
donnée à partir de l'ancienne, sans toucher à<br/>
l'originale. Exemple en Python : les chaînes, les<br/>
tuples sont immuables.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Elle ne peut pas être lue</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : une donnée immuable peut être lue<br/>
librement, c'est seulement la modification qui est<br/>
interdite.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Programmation fonctionnelle — Q04 : Fonctions de première classe</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Que signifie « les fonctions sont des objets de première<br/>
classe » dans un langage ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Cette propriété rend possibles les fonctions d'ordre<br/>
supérieur (map, filter, reduce), qui prennent ou<br/>
renvoient des fonctions, et qui sont au cœur du<br/>
paradigme fonctionnel.</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>Elles sont les plus rapides du programme</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : pas de lien avec la performance.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Elles peuvent être passées en paramètre, retournées par d'autres fonctions, et stockées dans des variables, comme n'importe quelle autre valeur</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : c'est une caractéristique majeure<br/>
des langages fonctionnels. Python, JavaScript,<br/>
OCaml, Haskell traitent les fonctions ainsi. C++,<br/>
Java l'ont ajouté plus tardivement.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Elles sont écrites en majuscules</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : aucun rapport avec la casse.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Elles sont les premières instructions du programme</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : aucun rapport avec l'ordre des instructions.<br/>
Le terme est conceptuel.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Programmation fonctionnelle — Q05 : Expression lambda</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>En Python, qu'est-ce qu'une <strong>expression lambda</strong> ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Le mot lambda vient du lambda-calcul de Church. En<br/>
Python, les lambda sont limitées à une seule<br/>
expression. Pour une fonction plus complexe, on utilise<br/>
def.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Une variable globale</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : aucun rapport avec les variables globales.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Une fonction anonyme définie en une seule ligne</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : lambda x: x <em> x est une fonction<br/>
anonyme qui prend x et renvoie son carré.<br/>
Équivalent à def f(x): return x </em> x mais sans<br/>
nom, utilisable directement comme expression.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Un type de boucle</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : ce n'est pas une boucle. C'est une fonction<br/>
anonyme.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Une instruction de débogage</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : aucun rapport avec le débogage.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Programmation fonctionnelle — Q06 : Fonction map</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Que fait la fonction map(f, L) en Python ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>map, filter et reduce (dans functools) sont les<br/>
trois fonctions d'ordre supérieur classiques en<br/>
programmation fonctionnelle. Elles correspondent à des<br/>
schémas d'usage très courants.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Elle filtre la liste selon un critère</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : c'est le rôle de filter, pas map.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Elle réduit la liste à une seule valeur</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : c'est le rôle de reduce, pas map.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Elle applique la fonction f à chaque élément de L et renvoie un itérateur des résultats</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : pour obtenir une liste, on fait<br/>
list(map(f, L)). Par exemple,<br/>
list(map(lambda x: x * 2, [1, 2, 3])) renvoie<br/>
[2, 4, 6].</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Elle modifie la liste L en y appliquant f directement</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : map ne modifie pas la liste d'origine.<br/>
Elle renvoie un nouvel itérateur (fonction pure).</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Programmation fonctionnelle — Q07 : Fonction filter</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Que fait filter(p, L) en Python ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Alternative idiomatique en Python avec<br/>
compréhension de liste :<br/>
[x for x in L if p(x)]. Souvent plus lisible que<br/>
filter en Python.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Elle compte le nombre d'éléments dans L</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : pour compter, on utilise len ou sum.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Elle conserve uniquement les éléments de L pour lesquels p(element) est vrai</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : par exemple,<br/>
list(filter(lambda x: x &gt; 0, [-1, 0, 1, 2]))<br/>
renvoie [1, 2]. Les éléments pour lesquels p<br/>
renvoie True sont conservés.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Elle modifie chaque élément de L</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : c'est plutôt le rôle de map.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Elle renvoie une liste vide</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : filter renvoie un itérateur des éléments<br/>
conservés, pas vide.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Programmation fonctionnelle — Q08 : Fonction reduce</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Quel est le rôle de reduce(f, L) (du module functools) ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>reduce (aussi appelé fold) est très puissant : il<br/>
capture les schémas de somme, produit, maximum,<br/>
concaténation, etc. En Python, il est moins idiomatique<br/>
qu'en Haskell, et souvent on lui préfère sum, max,<br/>
etc.</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>Trier la liste</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : c'est le rôle de sorted ou list.sort.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Combiner les éléments de L deux par deux à l'aide de f jusqu'à obtenir une seule valeur</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : par exemple,<br/>
reduce(lambda a, b: a + b, [1, 2, 3, 4]) calcule<br/>
((1 + 2) + 3) + 4 = 10. C'est l'agrégation par<br/>
excellence.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Faire une boucle</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : reduce est une <strong>abstraction</strong> de boucle<br/>
d'agrégation, mais ce n'est pas une boucle au sens<br/>
syntaxique.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Réduire la taille d'une liste en supprimant les doublons</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : ce n'est pas le rôle de reduce. Pour les<br/>
doublons, on utiliserait set(L).</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Programmation fonctionnelle — Q09 : Composition de fonctions</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Que signifie « composer deux fonctions f et g » ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>En programmation fonctionnelle, on construit des<br/>
programmes complexes en composant des fonctions<br/>
simples. Ce style favorise la <strong>réutilisation</strong> et la<br/>
<strong>modularité</strong>.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Les exécuter en parallèle</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : la composition est séquentielle (l'une<br/>
après l'autre).</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Créer une nouvelle fonction qui applique d'abord g, puis f au résultat (notée f \circ g)</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : (f \circ g)(x) = f(g(x)). La<br/>
composition de fonctions est la brique de base de la<br/>
programmation fonctionnelle, qui voit les programmes<br/>
comme des chaînes de transformations.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Les écrire dans le même fichier</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : aucun rapport. La composition est une<br/>
opération mathématique.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Les fusionner en une seule grosse fonction</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : la composition crée une nouvelle fonction<br/>
mais ne modifie pas f ni g ; elles restent<br/>
utilisables séparément.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Programmation fonctionnelle — Q10 : Récursivité en programmation fonctionnelle</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Pourquoi la <strong>récursivité</strong> est-elle privilégiée à la<br/>
boucle dans le paradigme fonctionnel ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Les langages fonctionnels purs (Haskell) n'ont même pas<br/>
de boucles : tout est exprimé par récursivité ou par<br/>
fonctions d'ordre supérieur.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Parce qu'elle est plus rapide</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : la récursivité est généralement aussi<br/>
rapide ou plus lente que les boucles, mais ce<br/>
n'est pas la raison de son emploi.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Parce qu'une boucle nécessite la modification d'une variable de compteur, ce qui contredit l'idéal d'immutabilité</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : for i in range(n) modifie<br/>
implicitement i. Une approche purement<br/>
fonctionnelle évite cela en utilisant des appels<br/>
récursifs avec de nouveaux paramètres.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Parce que les boucles n'existent pas en Python</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : Python a des boucles. C'est par<br/>
<strong>convention</strong> ou par <strong>style</strong> qu'on les évite en<br/>
programmation fonctionnelle.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Parce que c'est la mode</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : c'est une raison structurelle, pas un effet<br/>
de mode.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Programmation fonctionnelle — Q11 : Identifier une fonction pure</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Parmi les fonctions Python suivantes, laquelle est<br/>
<strong>pure</strong> ?</p>
<p>`<code><br/>
def f1(x): return x + 1<br/>
def f2(x): print(x); return x<br/>
def f3(L, x): L.append(x); return L<br/>
def f4(): return random.random()<br/>
</code>`</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Les effets de bord typiques : modifier une variable<br/>
globale, écrire dans un fichier, appeler print,<br/>
utiliser le hasard, lire l'horloge système, etc. Toutes<br/>
ces opérations rendent une fonction impure.</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>f1 et f4</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : f4 n'est pas pure. Pour les mêmes<br/>
arguments (aucun ici), elle renvoie des résultats<br/>
différents (génération aléatoire).</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>f1 et f2</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : f2 appelle print, ce qui est un effet<br/>
de bord (interaction avec le terminal).</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>f1 uniquement</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : f1 ne modifie rien et retourne<br/>
toujours la même valeur pour le même argument. f2<br/>
a un effet de bord (print), f3 modifie son<br/>
argument, f4 retourne un résultat différent à<br/>
chaque appel.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Toutes</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : seule f1 respecte les deux conditions de<br/>
pureté.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Programmation fonctionnelle — Q12 : Lambda avec map</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Que renvoie l'expression Python suivante ?</p>
<p>`<code><br/>
list(map(lambda x: x ** 2, [1, 2, 3, 4]))<br/>
</code>`</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Cette construction est très idiomatique en<br/>
programmation fonctionnelle. En Python, on peut aussi<br/>
écrire [x ** 2 for x in [1, 2, 3, 4]], qui est<br/>
souvent considéré plus lisible.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>[1, 4, 9, 16]</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : la lambda calcule le carré, et map<br/>
l'applique à chaque élément. On obtient<br/>
[1², 2², 3², 4²] = [1, 4, 9, 16].</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>[1, 2, 3, 4]</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : map applique la fonction à chaque<br/>
élément, donc transforme la liste.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>[1, 16]</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : map applique à <strong>chaque</strong> élément, on<br/>
n'en perd pas en chemin.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>[2, 4, 6, 8]</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : ce serait lambda x: x * 2, pas x <strong> 2.<br/>
</strong> est l'opérateur <strong>puissance</strong> en Python.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Programmation fonctionnelle — Q13 : Filter pour les nombres pairs</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Que renvoie cette expression ?</p>
<p>`<code><br/>
list(filter(lambda x: x % 2 == 0, range(10)))<br/>
</code>`</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Équivalent en compréhension de liste :<br/>
[x for x in range(10) if x % 2 == 0]. Les deux<br/>
formes sont fréquentes en Python.</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>[]</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : il y a bien des nombres pairs dans<br/>
range(10).</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>[1, 3, 5, 7, 9]</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : x % 2 == 0 teste si x est <strong>pair</strong>.<br/>
Donc on garde les pairs, pas les impairs.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>[0, 1, 2, ..., 9]</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : ce serait range(10) complet, sans filtre.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>[0, 2, 4, 6, 8]</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : filter conserve les éléments pour<br/>
lesquels la condition est vraie. range(10) produit<br/>
0, 1, \ldots, 9 ; on garde les pairs 0, 2, 4, 6, 8.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Programmation fonctionnelle — Q14 : Compréhension de liste</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Quelle est la <strong>compréhension de liste</strong> Python équivalente<br/>
à list(map(lambda x: x * 2, filter(lambda x: x &gt; 0, L))) ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Les compréhensions de liste, inspirées des langages<br/>
fonctionnels, s'intègrent naturellement à Python.<br/>
Elles combinent élégamment map et filter en<br/>
une seule expression. Pour réduire une liste à une<br/>
valeur unique, on utilise sum, max, min, etc.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>[x &gt; 0 * 2 for x in L]</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : syntaxiquement valide mais sémantiquement<br/>
faux. La condition est ailleurs.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>[x for x in L * 2]</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : cela multiplie la liste par 2 (deux<br/>
répétitions de la liste), pas chaque élément. De<br/>
plus, le filtre est absent.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>[L if x &gt; 0 for x in L]</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : syntaxe incorrecte de compréhension.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>[x * 2 for x in L if x &gt; 0]</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : on combine map et filter dans une<br/>
seule compréhension. Cette forme est plus lisible<br/>
et idiomatique en Python.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Programmation fonctionnelle — Q15 : Fonction d'ordre supérieur</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Quelle est la définition d'une <strong>fonction d'ordre<br/>
supérieur</strong> ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Les fonctions d'ordre supérieur sont la signature du<br/>
paradigme fonctionnel. Elles permettent l'abstraction<br/>
du comportement : par exemple, sorted(L, key=f)<br/>
laisse l'utilisateur définir comment trier sans changer<br/>
l'algorithme de tri.</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 fonction définie au niveau global</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : aucun rapport avec la portée.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Une fonction qui appelle d'autres fonctions</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : la plupart des fonctions appellent d'autres<br/>
fonctions. Le critère est plus précis.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Une fonction qui prend une fonction en argument et/ou en retourne une</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : map, filter, reduce, sorted<br/>
(avec key), les décorateurs sont des fonctions<br/>
d'ordre supérieur. Elles manipulent les fonctions<br/>
comme n'importe quelle autre valeur.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Une fonction très complexe</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : « ordre supérieur » est un terme technique,<br/>
pas un jugement de complexité.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Programmation fonctionnelle — Q16 : Mémoïsation et fonctions pures</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Pourquoi la mémoïsation est-elle particulièrement adaptée<br/>
aux fonctions pures ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>C'est aussi pour cela que des langages purs comme<br/>
Haskell peuvent automatiquement mémoïser des fonctions<br/>
sans surprise. Avec Python, il faut être prudent,<br/>
lru_cache ne fonctionne correctement qu'avec des<br/>
fonctions pures.</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>Une fonction pure renvoie toujours la même valeur pour les mêmes arguments, donc le cache est toujours fiable</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : si la fonction n'était pas pure (par<br/>
exemple, dépendait de l'horloge), le cache pourrait<br/>
renvoyer une valeur obsolète. La pureté garantit que<br/>
le résultat est invariable.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>La mémoïsation modifie la fonction</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : la mémoïsation enveloppe la fonction sans<br/>
la modifier. C'est la pureté qui rend cette<br/>
enveloppe correcte.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Les fonctions pures sont plus rapides</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : ce n'est pas une question de vitesse<br/>
intrinsèque, mais de <strong>correction</strong> de la mémoïsation.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Les fonctions pures n'ont pas besoin de mémoire</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : la mémoïsation <strong>utilise</strong> précisément de<br/>
la mémoire (un cache). C'est la fiabilité de cette<br/>
mise en cache qui dépend de la pureté.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Programmation fonctionnelle — Q17 : Calcul avec reduce</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Que calcule cette expression ?</p>
<p>`<code><br/>
from functools import reduce<br/>
reduce(lambda a, b: a * b, [1, 2, 3, 4, 5])<br/>
</code>`</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>reduce exprime des agrégations très variées : somme,<br/>
produit, max, min, concaténation. C'est l'opération<br/>
« repli » (<em>fold</em>) en programmation fonctionnelle.</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 maximum (5)</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : ce serait<br/>
reduce(lambda a, b: a if a &gt; b else b, ...).</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>La somme des éléments (15)</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : la lambda multiplie (*), pas additionne.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>La longueur (5)</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : ce serait len([...]), pas reduce.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Le produit des éléments (120)</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : on calcule<br/>
((((1 · 2) · 3) · 4) · 5) = 120,<br/>
autrement dit 5! = 120. C'est la <strong>factorielle</strong>.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Programmation fonctionnelle — Q18 : Transparence référentielle</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Que désigne la <strong>transparence référentielle</strong> d'une<br/>
expression ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>La transparence référentielle est synonyme de pureté.<br/>
Elle facilite le raisonnement sur le code : on peut<br/>
remplacer mentalement une expression par sa valeur<br/>
pour comprendre un programme.</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>L'expression contient des commentaires</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : aucun rapport avec les commentaires.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>L'expression est écrite en blanc sur fond noir</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : sigle inventé.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>L'expression peut être remplacée par sa valeur sans changer le comportement du programme</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : si f(3) renvoie toujours 9, alors<br/>
on peut remplacer f(3) par 9 partout dans le<br/>
code, sans rien casser. C'est une propriété forte<br/>
des fonctions pures.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>L'expression renvoie une référence vers un objet</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : aucun rapport avec les références ou les<br/>
pointeurs.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Programmation fonctionnelle — Q19 : Impératif vs fonctionnel</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Quel est l'équivalent <strong>fonctionnel</strong> du code impératif<br/>
suivant ?</p>
<p>`<code><br/>
total = 0<br/>
for x in L:<br/>
    if x &gt; 0:<br/>
        total += x ** 2<br/>
</code>`</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Le code fonctionnel est plus court, sans variable<br/>
modifiable, et exprime directement l'<strong>intention</strong><br/>
(« la somme des carrés des positifs ») plutôt que la<br/>
<strong>mécanique</strong> d'accumulation.</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>L.sum() if L &gt; 0</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : syntaxe incorrecte. Les listes Python n'ont<br/>
pas de méthode sum.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>sum(x  2 for x in L if x &gt; 0)</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : on combine filter (if x &gt; 0),<br/>
map (x ** 2) et reduce (sum) en une seule<br/>
expression. Pas de variable mutable, pas de boucle<br/>
explicite.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>reduce(L)</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : reduce requiert une fonction et une<br/>
séquence, pas seulement une séquence.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>for x in L: total += x  2</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : c'est une boucle impérative qui modifie<br/>
total. On veut s'en abstraire.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Programmation fonctionnelle — Q20 : Récursivité sans boucle</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Quelle est l'écriture <strong>récursive pure</strong> de la fonction<br/>
qui calcule la somme des éléments d'une liste ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Cette implémentation récursive est belle et simple,<br/>
mais en Python elle est limitée par la pile (~1000<br/>
éléments). Pour des listes plus longues, on combine<br/>
avec une stratégie (récursivité terminale, division<br/>
par moitié, ou plus simplement sum).</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><br/>
def somme(L):<br/>
    return sum(L)<br/>
</code>`</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : sum est correcte mais elle ne montre pas<br/>
la récursivité. Et elle utilise en interne une<br/>
boucle impérative.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>`<code><br/>
def somme(L):<br/>
    total = 0<br/>
    for x in L: total += x<br/>
    return total<br/>
</code>`</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : c'est l'écriture <strong>impérative</strong>. Elle<br/>
utilise une variable mutable (total), contraire à<br/>
l'idéal fonctionnel.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>`<code><br/>
def somme(L):<br/>
    if L == []:<br/>
        return 0<br/>
    return L[0] + somme(L[1:])<br/>
</code>`</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : aucune variable mutable, aucune<br/>
boucle. Juste un cas de base et un appel récursif.<br/>
C'est l'archétype du style fonctionnel pur.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>`<code><br/>
def somme(L):<br/>
    return reduce(lambda a, b: a + b, L)<br/>
</code>`</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : c'est aussi correct et fonctionnel, mais ce<br/>
n'est pas une définition <strong>récursive</strong> au sens<br/>
strict. La question demandait la récursivité<br/>
explicite.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Programmation fonctionnelle — Q21 : Mélange de paradigmes</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Un programme Python utilise une boucle for pour<br/>
parcourir une liste, puis appelle sorted avec une<br/>
fonction lambda comme critère. Combien de paradigmes<br/>
de programmation différents ce code combine-t-il ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Python est un langage <strong>multi-paradigme</strong> : il<br/>
permet d'écrire dans le style impératif (boucles,<br/>
affectations), fonctionnel (lambda, map,<br/>
compréhensions) ou objet (classes), et de<br/>
combiner librement les trois selon les besoins.</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>Aucun, ce n'est pas un vrai programme</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : c'est bien un programme valide, et il<br/>
utilise plusieurs paradigmes.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Deux : impératif (la boucle for) et fonctionnel (le tri par lambda)</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : c'est exactement ce que dit le<br/>
programme officiel : « Dans un même programme,<br/>
on peut utiliser des paradigmes différents. »</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Trois : impératif, fonctionnel et objet</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : aucune classe ni objet n'est défini<br/>
dans cet exemple, donc le paradigme objet n'est<br/>
pas mobilisé.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Un seul, l'impératif</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : la boucle for est bien impérative,<br/>
mais l'usage de sorted avec une lambda relève<br/>
du style fonctionnel.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Programmation fonctionnelle — Q22 : Calculer la somme des carrés</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>On veut calculer la somme des carrés des entiers<br/>
d'une liste nombres. Quel code suit le <strong>style<br/>
fonctionnel</strong> ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Le style fonctionnel privilégie les expressions<br/>
sans état modifiable. La compréhension de liste et<br/>
les fonctions comme sum, map, filter<br/>
permettent souvent d'écrire des traitements de<br/>
données très concis dans ce style.</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/>
total = 0<br/>
for n in nombres:<br/>
    total = total + n * n<br/>
</code>`</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : ce code est <strong>impératif</strong> : il modifie<br/>
une variable total à chaque itération.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>`<code>python<br/>
class Sommateur:<br/>
    def __init__(self):<br/>
        self.total = 0<br/>
    def ajouter(self, n):<br/>
        self.total += n * n<br/>
</code>`</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : ce code définit une classe ; c'est le<br/>
style <strong>objet</strong>, pas fonctionnel.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>`<code>python<br/>
total = nombres<br/>
</code>`</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : ce code ne calcule pas du tout la<br/>
somme des carrés.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>`<code>python<br/>
total = sum(n * n for n in nombres)<br/>
</code>`</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : ce code est <strong>fonctionnel</strong> : il<br/>
construit une expression sans variable d'état<br/>
intermédiaire et passe le résultat à la fonction<br/>
sum. Pas d'effet de bord.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Programmation fonctionnelle — Q23 : Choisir un paradigme</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Pour écrire un script court qui transforme une<br/>
liste de prix en y appliquant une remise de 10\%,<br/>
quel <strong>paradigme</strong> est le plus naturel en Python ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Une même tâche peut souvent s'écrire dans plusieurs<br/>
paradigmes. Le bon choix dépend de la nature du<br/>
problème : transformations de données pour le<br/>
fonctionnel, modélisation d'entités pour l'objet,<br/>
séquences d'instructions pour l'impératif. Python<br/>
permet de mélanger les trois.</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>Une approche fonctionnelle avec une compréhension de liste ou un map sur une lambda</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : la transformation d'une liste en<br/>
une autre par une fonction simple est typique du<br/>
style fonctionnel. Une compréhension de liste<br/>
comme [p * 0.9 for p in prix] est concise et<br/>
claire.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Un paradigme logique type Prolog</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Possible théoriquement mais inadapté ici, et<br/>
Prolog n'est pas Python. Le paradigme logique<br/>
n'est pas étudié au lycée.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Une approche objet avec une classe Remiseur et une méthode appliquer</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Possible mais nettement excessif pour une<br/>
transformation de liste de quelques lignes. La<br/>
POO se justifie quand on modélise des entités<br/>
avec un état et plusieurs comportements.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Aucun paradigme : il faut tout écrire à la main, avec des goto</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : il n'existe pas de goto en Python, et<br/>
aucun paradigme moderne ne le promeut.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Programmation fonctionnelle — Q24 : Programmation fonctionnelle et parallélisme</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Pourquoi la programmation fonctionnelle est-elle<br/>
particulièrement adaptée au calcul <strong>parallèle</strong> ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>C'est l'argument phare des promoteurs du fonctionnel à<br/>
l'ère des processeurs multi-cœurs. Spark, MapReduce,<br/>
les architectures d'informatique en nuage reposent<br/>
largement sur ces principes.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Elle utilise plus de cœurs du processeur</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : ce n'est pas la cause, c'est l'effet<br/>
recherché. La cause est plus profonde.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Elle utilise moins de mémoire</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : au contraire, l'immutabilité peut consommer<br/>
plus de mémoire (création de nouveaux objets plutôt<br/>
que modification en place).</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Elle est plus simple à apprendre</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : c'est subjectif, et de toute façon pas la<br/>
raison de l'aptitude au parallélisme.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>L'absence d'effets de bord et l'immutabilité éliminent les conflits d'accès aux données partagées</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : en programmation impérative, deux<br/>
threads modifiant la même variable doivent se<br/>
synchroniser, ce qui est complexe et lent. Avec des<br/>
données immuables, aucune synchronisation n'est<br/>
requise, on peut paralléliser sans crainte.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Programmation fonctionnelle — Q25 : Comparaison des paradigmes</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Parmi les affirmations suivantes, laquelle est <strong>vraie</strong> ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>L'idéal pragmatique : utiliser le bon paradigme pour<br/>
le bon problème. Une bonne formation NSI inclut donc<br/>
les deux pour développer la flexibilité de pensée<br/>
algorithmique.</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 programmation fonctionnelle remplace définitivement l'orientée objet</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : les deux paradigmes coexistent et se<br/>
complètent. La plupart des langages modernes sont<br/>
multi-paradigmes (Python, JavaScript, Scala).</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>La programmation fonctionnelle ne fonctionne que sur les ordinateurs récents</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : Lisp date de 1958 et tournait sur les<br/>
premiers ordinateurs. La programmation fonctionnelle<br/>
est antérieure à l'orientée objet.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>La programmation fonctionnelle interdit l'utilisation des classes</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : on peut utiliser des classes en<br/>
programmation fonctionnelle, surtout dans des<br/>
langages multi-paradigmes. Les puristes les évitent,<br/>
mais ce n'est pas une interdiction du paradigme<br/>
lui-même.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>La programmation fonctionnelle et l'orientée objet sont des paradigmes complémentaires, chacun adapté à certaines situations</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : OO modélise des entités avec état<br/>
et comportement (interfaces graphiques, simulation,<br/>
jeux). Fonctionnelle modélise des transformations<br/>
de données (calcul, science des données). Beaucoup<br/>
de programmes mélangent les deux.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Programmation fonctionnelle — Q26 : Fermeture (closure)</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>On considère le code Python suivant :<br/>
``<br/>
def faire_compteur():<br/>
    n = 0<br/>
    def incrementer():<br/>
        nonlocal n<br/>
        n += 1<br/>
        return n<br/>
    return incrementer</p>
<p>c = faire_compteur()<br/>
print(c(), c(), c())<br/>
<code><br/>
Que renvoie l'appel print(c(), c(), c())</code> et de<br/>
quel concept s'agit-il ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Les fermetures permettent de créer des fonctions avec<br/>
état, sans recourir aux classes. Très utilisées en<br/>
JavaScript, Python, Lisp. Elles sont à la base des<br/>
décorateurs et des fonctions partiellement<br/>
appliquées.</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>Affiche 1 2 3. C'est un exemple de fermeture<br/>
(closure) : la fonction interne incrementer<br/>
capture la variable n de la fonction englobante,<br/>
même après que celle-ci a terminé son exécution</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : incrementer « se souvient » de<br/>
la variable n de l'environnement où elle a été<br/>
définie. Chaque appel à c() incrémente cette<br/>
variable persistante. La fermeture est un concept<br/>
fondamental qui montre que les fonctions de<br/>
première classe peuvent porter avec elles un<br/>
contexte.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Lève une erreur car n est une variable locale à<br/>
faire_compteur</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : grâce au mot-clé nonlocal (ou même sans<br/>
en lecture), Python autorise l'accès à n.<br/>
C'est précisément le mécanisme de fermeture.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Affiche 1 1 1 car n est réinitialisé à chaque<br/>
appel</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : c'est précisément ce que la fermeture<br/>
empêche. La variable n est capturée et persistée<br/>
entre les appels. Sans nonlocal, on aurait une<br/>
erreur car on tenterait de modifier une variable<br/>
qui semblerait locale.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Affiche 0 0 0 car n ne peut pas être modifié<br/>
dans une fonction interne</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : avec nonlocal n, on indique à Python<br/>
que n se réfère à la variable de la fonction<br/>
englobante, et qu'on peut la modifier. La sortie<br/>
est bien 1 2 3.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Programmation fonctionnelle — Q27 : Décorateur Python</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Les décorateurs Python (@nom) sont une application<br/>
directe d'un concept fondamental de la programmation<br/>
fonctionnelle. Lequel ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Exemple de décorateur classique : @functools.lru_cache<br/>
qui ajoute une mémoïsation à n'importe quelle fonction<br/>
pure. Autres : @property (transformer une méthode<br/>
en attribut), @staticmethod, @classmethod. Tous<br/>
reposent sur l'idée de manipuler les fonctions comme<br/>
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>La compréhension de liste</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : la compréhension de liste est une<br/>
syntaxe fonctionnelle pour transformer des<br/>
collections, pas pour modifier des fonctions.<br/>
Aucun lien avec les décorateurs.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Le filtrage par motif (<em>pattern matching</em>)</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : le filtrage par motif est une<br/>
fonctionnalité distincte (introduite en Python<br/>
3.10 avec match). Il n'a aucun rapport avec<br/>
les décorateurs.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>La récursivité</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : un décorateur n'a aucun rapport avec la<br/>
récursivité. Il s'agit d'un mécanisme totalement<br/>
différent. La récursivité est l'auto-appel d'une<br/>
fonction.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Les fonctions d'ordre supérieur : un décorateur<br/>
est une fonction qui prend une fonction en<br/>
paramètre et renvoie une nouvelle fonction<br/>
(souvent enrichie d'un comportement<br/>
supplémentaire)</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : la syntaxe @decorator au-dessus<br/>
de def f(): ... est strictement équivalente à<br/>
f = decorator(f). Le décorateur reçoit la<br/>
fonction f en paramètre et renvoie une nouvelle<br/>
fonction qui généralement appelle f en y<br/>
ajoutant des comportements (mesure du temps,<br/>
journalisation, mémoïsation, vérification de<br/>
droits, etc.).</p>]]></text>
    </feedback>
  </answer>
</question>

</quiz>
