La seule fois où vous devrez vous rendre à Paris 8. Il y avait la possibilité d'effectuer ce regroupement à l'étranger (hors Europe) par le passé, mais cette possiblité semble avoir disparue (à confirmer).
Le regroupement ressemble à (mais n'est pas) un examen. Trois matières de L1 sont évaluées sur une demi-journée:
Chaque prof décide si vous êtes convocable ou non, suivant votre avancement dans son cours. Il faut être convocable à tous les cours pour être convoqués. Vous devez venir avec votre propre ordinateur. N'oubliez pas un adaptateur secteur si vous venez de l'étranger. Vous aurez accès à vos notes, à Internet, etc.
Il y a en général deux regroupements par an, un en juin ou juillet et un en septembre. Il n'y a pas de quota à proprement parler, mais parfois un problème de place (salles disponibles pas assez grande). Dans ce cas, vous pouvez ne pas être convoqué et devoir attendre la session suivante.
Chaque matière est évaluée séparement. Si vous échouez sur une matière, vous n'aurez à repasser que cette matière lors d'un prochain regroupement, pas toutes les matières. Lorsque vous aurez réussi toutes les matières, ce cours (EC) sera validé et vous aurez la note de 10 (les “vraies" notes ne sont pas communiquées). Cette note ne compte pas dans la moyenne de l'année. En d'autres termes, c'est une étape obligatoire mais qui ne compte pas. Vous ne pouvez pas valider la L1 ni obtenir des compensations sans cet EC. Si vous avez 40 ECTS, vous pouvez passer en L1/L2 (AJAC “ajourné autorisé à continuer”) même sans avoir validé le regroupement.
Au niveau des notes et de la validation, il n'y a pas de lien entre le regroupement et les trois matières. Vous pouvez avoir validé le cours (EC) de, par exemple, “Programmation fonctionnelle” et avoir échoué dans (ou pas encore passé) cette matière au regroupement. Et inversement.
Vous trouverez certains des exercices des années passées avec des corrections sur GitHub.
Les épreuves de programmation fonctionnelles sont très souvent sur le même modèle:
A titre d'exemple, prenons l'épreuve de Juin 2023. Elle débute ainsi:
Epreuve 1
Soient deux listes plates, la première étant une liste plate de places boursières, la seconde une liste contenant des matières premières, construire récursivement une liste comme suit (chaque bourse a toutes les matières) :
liste_bourses : (bourse1 bourse2... bourseN)
liste_matières : (matière1 matière2... matièreN)
=> ((bourse1 (matière1) (matière2) ... (matièreN)) ... (bourse2 (matière1) (matière2)... (matièreN)))On appellera cette liste : Cours-bourses. Cette partie de l'exercice est très simple pour ceux qui ont révisé, ce qui fait que c'est la suite qui compte vraiment.
On va découper ce problème en deux étapes:
((matière1) (matière2) … (matièreN)
à partir de la liste (matière1 matière2... matièreN),
Pour la première étape, on part de cette liste:
Et on veut arriver à cette liste:
On procède par récurrence:
Il y a plusieurs manières de faire, mais un code possible est le suivant:
(defun construit-matières (matières)
(cond
((atom matières) nil)
(t
(cons
(cons (car matières) nil)
(construit-matières (cdr matières)) ) ) ) )
Note: Pendant l'épreuve, vous préoccupez pas trop du pretty-print, vous ne serez pas noté là dessus.
On peut passer à l'étape suivante et construire la liste demandée. On part de cette liste:
Et on veut arriver à cette liste:
La partie entourée en rouge est ce que nous avons obtenu précédemment avec notre fonction construit-matières
. Un code possible est le suivant, très similaire à la fonction précédente:
(defun construit-cours-bourse (bourses matières)
(cond
((atom bourses) nil)
(t
(cons
(cons
(car bourses)
(construit-matières matières) )
(construit-cours-bourse (cdr bourses) matières) ) ) ) )
On peut tester cette fonction et construire la liste `Cours-bourses` demandée:
(setq liste_bourses '(Frankfort Paris Londres Bejing))
(setq liste_matières '(blé soja café))
(setq Cours-bourses (construit-cours-bourse liste_bourses liste_matières))
; => ((Frankfort (blé) (soja) (café)) (Paris (blé) (soja) (café)) (Londres (blé) (soja) (café)) (Bejing (blé) (soja) (café)))
L'énoncé se poursuit ainsi:
Écrire une fonction avec comme argument Cours-bourses qui interroge l'utilisateur (avec un (read)) pour obtenir le prix de chaque matière dans chaque place boursière et qui construit la liste suivante :
=> ((bourse1 (matière1 . prix) (matière2 . prix)... ) etc.
La fonction parcourt toutes les places boursières et toutes les matières, et, pour chaque couple place boursière – matière première, pose la question :
"Quel est le prix de <blé par exemple> à <Frankfort par exemple> ? (écrivez un nombre)"
Puis effectue un read de la réponse, vérifie que c'est bien un nombre, et insère (matière1 . prix) dans la nouvelle liste.Astuce : pour poser la question, il faut utiliser la fonction (print <message>) ; vous pouvez imprimer avec cinq fois la fonction print (pour "Quel est le prix de", puis pour <matière première en cours>, puis pour "à", puis pour <place boursière en cours>, puis pour " ? (écrivez un nombre)"), ou alors construire la chaîne avec string-concat et l'imprimer avec un seul print. Faites un (terpri) à la fin pour aller à la ligne. Pour récupérer la réponse, il suffit de la fonction (read).
Conseil : écrivez une sous-fonction juste pour imprimer la question et récupérer la réponse.
Comme conseillé, on crée une fonction pour imprimer la question et récupérer la réponse:
Note: On pourrait aussi vérifier que le nombre est bien strictement positif mais on suppose qu'un cours négatif est possible.
Cela peut donner le code suivant:
(defun demande-un-cours (matière bourse &aux prix)
(print (string-concat "Quel est le prix de/du " (string matière) " à la bourse de " (string bourse) " ? (écrivez un nombre)"))
(setq prix (read))
(cond
((numberp prix) prix)
(t
(print "Ce n'est pas un nombre")
(demande-un-cours matière bourse)) ) )
On peut ensuite créer une sous-fonction dont le but est de demander les prix des matières pour une bourse donnée en argument. Là encore, on procède par récurrence pour parcourir la liste des matières et construire la liste. Les deux difficultés sont de:
car
, cdr
ou leurs dérivés comme caar
.Ici, on va choisir de passer en argument la liste de listes des matières (construite plus haut). On veut récupérer le symbole de la matière courante (en tête de liste).
Pour récupérer ce symbole (blé), on effectue donc deux opérations car
ce qui donne caar
. Pour avancer dans la liste, on effectue une opération cdr
. On construit une liste suivant le structure que l'on souhaite obtenir au final, c'est à dire la la forme ((matière . prix) …)
:
Cela donne le code suivant:
(defun demande-les-cours (bourse matières)
(cond
((atom matières) nil)
(t
(cons
(cons
(caar matières)
(demande-un-cours (caar matières) bourse) )
(demande-les-cours bourse (cdr matières)) ) ) ) )
Il ne reste qu'à parcourir la liste des bourses avec une dernière fonction, toujours sur le même modèle, pour construire notre liste finale à partir d'une liste avec le format de Cours-bourses
:
(defun demande-tous-les-cours (cours-bourses)
(cond
((atom cours-bourses) nil)
(t
(cons
(cons
(caar cours-bourses)
(demande-les-cours (caar cours-bourses) (cdar cours-bourses)) )
(demande-tous-les-cours (cdr cours-bourses)) ) ) ) )
On vérifie le bon fonctionnement de nos fonctions. D'abord de demande-un-cours
:
(demande-un-cours 'blé 'Frankfurt)
; => "Quel est le prix de/du blé à la bourse de Frankfurt ? (écrivez un nombre)" 2.4
; => 2.4
Puis de demande-les-cours
:
(demande-les-cours 'Frankfurt '((blé) (soja) (café) (maïs)))
"Quel est le prix de/du blé à la bourse de Frankfurt ? (écrivez un nombre)" 1.1
"Quel est le prix de/du soja à la bourse de Frankfurt ? (écrivez un nombre)" 1.2
"Quel est le prix de/du café à la bourse de Frankfurt ? (écrivez un nombre)" 1.3
"Quel est le prix de/du maïs à la bourse de Frankfurt ? (écrivez un nombre)" 1.4
((blé . 1.1) (soja . 1.2) (café . 1.3) (maïs . 1.4))
Et enfin de demande-tous-les-cours
avec comme argument Cours-bourses
:
(setq liste_bourses '(Frankfort Paris Londres Bejing))
(setq liste_matières '(blé soja café))
(setq Cours-bourses (construit-cours-bourse liste_bourses liste_matières))
; => ((Frankfort (blé) (soja) (café)) (Paris (blé) (soja) (café)) (Londres (blé) (soja) (café)) (Bejing (blé) (soja) (café)))
(demande-tous-les-cours Cours-bourses)
; => "Quel est le prix de/du blé à la bourse de Frankfort ? (écrivez un nombre)" 1.2
; =>
; => "Quel est le prix de/du soja à la bourse de Frankfort ? (écrivez un nombre)" 2.3
; =>
; => "Quel est le prix de/du café à la bourse de Frankfort ? (écrivez un nombre)" 3.4
; =>
; => "Quel est le prix de/du blé à la bourse de Paris ? (écrivez un nombre)" 4.5
; =>
; => "Quel est le prix de/du soja à la bourse de Paris ? (écrivez un nombre)" 5.6
; =>
; => "Quel est le prix de/du café à la bourse de Paris ? (écrivez un nombre)" 6.7
; =>
; => "Quel est le prix de/du blé à la bourse de Londres ? (écrivez un nombre)" 7.8
; =>
; => "Quel est le prix de/du soja à la bourse de Londres ? (écrivez un nombre)" 8.9
; =>
; => "Quel est le prix de/du café à la bourse de Londres ? (écrivez un nombre)" 9.0
; =>
; => "Quel est le prix de/du blé à la bourse de Bejing ? (écrivez un nombre)" 1.1
; =>
; => "Quel est le prix de/du soja à la bourse de Bejing ? (écrivez un nombre)" 1.2
; =>
; => "Quel est le prix de/du café à la bourse de Bejing ? (écrivez un nombre)" 1.3
; => ((Frankfort (blé . 1.2) (soja . 2.3) (café . 3.4)) (Paris (blé . 4.5) (soja . 5.6) (café . 6.7)) (Londres (blé . 7.8) (soja . 8.9) (café . 9.0)) (Bejing (blé . 1.1) (soja . 1.2) (café . 1.3)))
Epreuve 2
Écrire une variante de la fonction finale de l'épreuve 1, qui modifie Cours-bourses au lieu de construire une nouvelle liste.
Dans la partie précédente, on a construit à chaque fois de nouvelles listes (avec cons
). Dans cette partie, on nous demande de ne pas construire de nouvelles listes mais de modifier la liste existante. En d'autres termes, on part de cette liste (Cours-bourses
):
Et on veut la modifier pour arriver à cette liste:
Ce que l'on veut, c'est donc modifier le cdr
du doublet dont le car
contient le symbole de la matière. Cela se fait avec la fonction rplacd
(remplacer le cdr). On va donc réécrire nos fonctions pour modifier la liste. La fonction demande-un-cours
ne change pas car elle retourne simplement un prix. La fonction demande-les-cours
part de cette liste:
et doit la modifier pour arriver à cette liste:
En partant du début de la liste, on doit donc modifier le cdr
du doublet donné par le car
de la liste. La valeur à mettre est donnée par la fonction demande-un-cours
comme dans la version précédente. Cela donne le code suivant:
(defun demande-les-cours (bourse matières)
(cond
((atom matières) nil)
(t
(rplacd
(car matières)
(demande-un-cours (caar matières) bourse) )
(demande-les-cours bourse (cdr matières)) ) ) )
A noter que cette fonction est toujours récursive. Dans la partie 1, la récursivité se trouvait dans un appel à cons
car on construisait un doublet avec la suite de la liste construite par récurrence. Dans cette partie, comme on ne construit pas la liste mais on la modifie, il n'y a pas de cons
. A la place, on appelle simplement la fonction elle-même avec la suite de la liste.
La fonction demande-tous-les-cours
devient très simple car, là aussi, il n'y a plus besoin de construire quoi que ce soit. On doit juste parcourir la liste par récurrence et appeler demande-les-cours
(qui modifie la liste). Cela donne:
(defun demande-tous-les-cours (cours-bourses)
(cond
((atom cours-bourses) nil)
(t
(demande-les-cours (caar cours-bourses) (cdar cours-bourses))
(demande-tous-les-cours (cdr cours-bourses)) ) ) )
On vérifie le bon fonctionnement de nos fonctions. D'abord de demande-les-cours
:
(setq liste '((blé) (soja) (café) (maïs)))
; => ((blé) (soja) (café) (maïs))
(demande-les-cours 'Frankfurt liste)
; => "Quel est le prix de/du blé à la bourse de Frankfurt ? (écrivez un nombre)" 1.2
; =>
; => "Quel est le prix de/du soja à la bourse de Frankfurt ? (écrivez un nombre)" 2.3
; =>
; => "Quel est le prix de/du café à la bourse de Frankfurt ? (écrivez un nombre)" 3.4
; =>
; => "Quel est le prix de/du maïs à la bourse de Frankfurt ? (écrivez un nombre)" 4.5
; => nil
liste
; => ((blé . 1.2) (soja . 2.3) (café . 3.4) (maïs . 4.5))
Puis de demande-tous-les-cours
avec comme argument Cours-bourses
:
(setq Cours-bourses (construit-cours-bourse liste_bourses liste_matières))
; => ((Frankfort (blé) (soja) (café)) (Paris (blé) (soja) (café)) (Londres (blé) (soja) (café)) (Bejing (blé) (soja) (café)))
(demande-tous-les-cours Cours-bourses)
; => "Quel est le prix de/du blé à la bourse de Frankfort ? (écrivez un nombre)" 1.1
; =>
; => "Quel est le prix de/du soja à la bourse de Frankfort ? (écrivez un nombre)" 1.2
; =>
; => "Quel est le prix de/du café à la bourse de Frankfort ? (écrivez un nombre)" 1.3
; =>
; => "Quel est le prix de/du blé à la bourse de Paris ? (écrivez un nombre)" 2.1
; =>
; => "Quel est le prix de/du soja à la bourse de Paris ? (écrivez un nombre)" 2.2
; =>
; => "Quel est le prix de/du café à la bourse de Paris ? (écrivez un nombre)" 2.3
; =>
; => "Quel est le prix de/du blé à la bourse de Londres ? (écrivez un nombre)" 3.1
; =>
; => "Quel est le prix de/du soja à la bourse de Londres ? (écrivez un nombre)" 3.2
; =>
; => "Quel est le prix de/du café à la bourse de Londres ? (écrivez un nombre)" 3.3
; =>
; => "Quel est le prix de/du blé à la bourse de Bejing ? (écrivez un nombre)" 4.1
; =>
; => "Quel est le prix de/du soja à la bourse de Bejing ? (écrivez un nombre)" 4.2
; =>
; => "Quel est le prix de/du café à la bourse de Bejing ? (écrivez un nombre)" 4.3
; => nil
Cours-bourses
; => ((Frankfort (blé . 1.1) (soja . 1.2) (café . 1.3)) (Paris (blé . 2.1) (soja . 2.2) (café . 2.3)) (Londres (blé . 3.1) (soja . 3.2) (café . 3.3)) (Bejing (blé . 4.1) (soja . 4.2) (café . 4.3)))