Skip to content

2021/2022-s2

L'épreuve dure 1h30.

Elle se déroule en mode examen, pour lequel l'accès au web est bloqué, excepté les sites suivants :

Vous devez travailler directement sur le fichier traite_csv.py fourni et présent dans le dossier exam se trouvant sur le bureau de votre session d'examen. Pour chaque question ci dessous, vous devez compléter un ou plusieurs TODO du fichier traite_csv.py. Ces TODO sont identifiés par des numéros correspondant au numéro de la question.

Vous devez envoyer votre travail sur un serveur, toutes les 15 minutes environ, en cliquant sur ENVOYER se trouvant également sur le bureau.

À la fin de l'examen il faut cliquer sur TERMINER, toujours sur le bureau, et ne surtout pas éteindre la machine à la main en appuyant sur le bouton de mise/arrêt sous tension.

Enfin, le module traceur.py vous est fourni à côté du fichier traite_csv.py à compléter pour vous aider à déboguer visuellement si cela vous aide.

Contexte

On s’intéresse pour cet examen à la lecture et au traitement d’un fichier de notes au format CSV. Dans tous l'examen, nous travaillerons avec le fichier notes.csv fourni et présent dans le dossier exam.

Le format CSV est un format de fichier très simple pour le stockage de tableaux de données. Un fichier CSV contient un unique tableau 2D. Chaque ligne du fichier est une ligne du tableau et sur chaque ligne les données de chaque colonne sont séparées par une virgule. Dans notre cas, une ligne correspond aux données d’un étudiant et les colonnes sont les suivantes :

  • prénom (chaîne de caractères);
  • nom (chaîne de caractères);
  • note à l’examen numéro 0 (entier) ;
  • note à l’examen numéro 1 (entier) ;
  • note à l’examen numéro 2 (entier).

Si l’on examine par exemple les trois premières lignes du fichier notes.csv affichées ci-dessous on voit que François Pignon a une note de 15 à l’examen 0, 16 à l’examen 1 et 6 à l’examen 2. À la ligne suivante, on passe à un nouvel étudiant nommé Juste Leblanc et ensuite à une étudiante nommée Marlène Sasseur.

1
2
3
François,Pignon,15,16,6
Juste,Leblanc,15,0,8
Marlène,Sasseur,12,16,9

Partie 1 : lecture d'un fichier CSV

On se propose de stocker les données de chaque étudiant dans un namedtuple que l'on appellera Etudiant. Ce namedtuple se compose de trois attributs :

  • prenom qui est une chaîne de caractères ;
  • nom qui est une chaîne de caractères ;
  • notes qui est un tuple composé de trois entiers compris entre 0 et 20 représentant les notes au trois examens (notes[0] est la note à l'examen 0).

Question 0

Analysez le code de la fonction fournie teste puis appelez cette dernière (#TODO 0 à la fin du fichier) lorsque le programme traite_csv.py est invoqué en tant que programme principal.

Dans la suite, on testera donc l'implémentation de nos fonctions en lançant traite_csv.py en tant que programme principal et en analysant les sorties générées par la fonction teste.

Question 1

Définissez le namedtuple Etudiant (#TODO 1.0 et #TODO 1.1) et implémentez la fonction lit_fichier (#TODO 1.2).

On rappelle que toute chaîne de caractères Python dispose d’une méthode split permettant de la décomposer en sous-chaînes selon un séparateur donné. Par exemple, "Ah bon,il n'a pas de prénom,?".split(",") renvoie la list ["Ah bon", "il n'a pas de prénom", "?"].

Question 2

Implémentez la fonction génératrice lit_fichier_gen (#TODO 2) qui renvoie un générateur permettant d'itérer sur tous les étudiants présents dans le fichier CSV passé en paramètre. L'objectif est exactement le même que celui de lit_fichier mais la fonction génératrice permet d'économiser du temps et de la mémoire dans le cas où le fichier n'a pas besoin d'être parcouru intégralement.

Partie 2 : analyse des données

On va maintenant écrire un certain nombre de fonctions d'analyse et de tri des étudiants. Ces fonctions prennent toutes en entrée une list contenant des instances du namedtuple Etudiant telle que renvoyée par la fonction lit_fichier implémentée dans la partie 1.

On cherche lorsque c'est possible à réaliser les traitements en une seule passe sur les données. On considère également que la list d'étudiants passée en paramètre de ces fonctions est toujours non vide.

Question 3

Implémentez la fonction calcule_moyennes (#TODO 3) qui calcule la moyenne de la promotion pour chacun des trois examens.

Question 4

Implémentez la fonction génératrice recupere_etudiants_avec_un_20 (#TODO 4) qui renvoie un générateur permettant d'itérer sur les étudiants ayant au moins une note de 20/20.

Question 5

Implémentez la fonction recupere_minis_maxis_names (TODO 5) qui renvoie les étudiants ayant la note minimale pour chaque examen.

Question 6

Implémentez la fonction recupere_classement (TODO 6) qui renvoie les étudiants classés selon leur moyenne.

Partie 3 : histogrammes

On cherche à visualiser graphiquement les notes obtenues à chaque épreuve. Comme le montre l'image ci-dessous, on se propose de dessiner pour chaque note possible (de 0 à 20) une barre verticale sous forme d’un rectangle rouge. Pour chaque note n, la largeur du rectangle est fixée à 20 et sa hauteur à 20 fois le nombre d’étudiants ayant une note de n.

Question 7

Complétez la fonction genere_histogramme (TODO 7) qui prend un itérable sur les étudiants, ainsi qu’un numéro d’épreuve (entre 0 et 2), générant un histogramme en SVG et renvoyant le nom du fichier créé. Par souci de simplicité, on n'utilisera pas de module svg.py. On générera donc directement le code SVG depuis traite_csv.py en se basant sur le code SVG affiché ci-dessous.

Voici ce que doit générer votre fonction genere_histogramme pour l'examen 0 sur le fichier notes.csv présent dans votre dossier exam.

histogramme

Et voici le code SVG de cet histogramme :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
<svg width='420' height='120'>
<rect width='420' height='120' fill='white'/>
<text x='0' y='120'>0</text>
<text x='20' y='120'>1</text>
<text x='40' y='120'>2</text>
<text x='60' y='120'>3</text>
<rect width='20' height='20' x='80' y='80' fill='red'/>
<text x='80' y='120'>4</text>
<text x='100' y='120'>5</text>
<rect width='20' height='40' x='120' y='60' fill='red'/>
<text x='120' y='120'>6</text>
<rect width='20' height='60' x='140' y='40' fill='red'/>
<text x='140' y='120'>7</text>
<rect width='20' height='80' x='160' y='20' fill='red'/>
<text x='160' y='120'>8</text>
<rect width='20' height='20' x='180' y='80' fill='red'/>
<text x='180' y='120'>9</text>
<rect width='20' height='20' x='200' y='80' fill='red'/>
<text x='200' y='120'>10</text>
<text x='220' y='120'>11</text>
<rect width='20' height='100' x='240' y='0' fill='red'/>
<text x='240' y='120'>12</text>
<rect width='20' height='60' x='260' y='40' fill='red'/>
<text x='260' y='120'>13</text>
<rect width='20' height='40' x='280' y='60' fill='red'/>
<text x='280' y='120'>14</text>
<rect width='20' height='80' x='300' y='20' fill='red'/>
<text x='300' y='120'>15</text>
<rect width='20' height='20' x='320' y='80' fill='red'/>
<text x='320' y='120'>16</text>
<rect width='20' height='20' x='340' y='80' fill='red'/>
<text x='340' y='120'>17</text>
<rect width='20' height='20' x='360' y='80' fill='red'/>
<text x='360' y='120'>18</text>
<text x='380' y='120'>19</text>
<rect width='20' height='40' x='400' y='60' fill='red'/>
<text x='400' y='120'>20</text>
</svg>