Exercice 1 : Range¶
- Définissez la fonction
range: ?from:int -> ?step:int -> int -> int listavec un argument obligatoire et deux arguments optionnels. On pourra par exemple l'utiliser de la façon suivante:
range 5renvoie[0; 1; 2; 3; 4]range ~from:3 5renvoie[3; 4]range ~from:2 ~step:2 5renvoie[2; 4].
Pour simplifier, on supposera que l'argument step est toujours un entier strictement positif.
- Ajoutez un argument optionnel "sans valeur par défaut"
?truncate:intqui, s'il est définit tronque la liste produite pour qu'elle ne comporte quenéléments. Par exemple,range ~from:1 ~step:2 ~truncate:2 5renvoie[1; 3].
Fichiers CSV¶
Dans la suite de ce TD, on travaille sur des fichiers au format CSV (Comma-Separated Values). Un fichier CSV est un fichier texte dont le contenu représente un tableau. Chaque ligne du fichier correspond à une ligne du tableau. Les différentes valeurs composant une ligne sont séparées par des virgules.
Par exemple, le fichier exemple.csv dont le contenu est
Identifiant,Partiel,Projet,Final
,0.3,0.3,0.4
ab12345678,12,15,14
cd98765432,10,,9
ef24681357,11,13
correspond au tableau
------------------------------------------
| Identifiant | Partiel | Projet | Final |
------------------------------------------
| | 0.3 | 0.3 | 0.4 |
------------------------------------------
| ab12345678 | 12 | 15 | 14 |
------------------------------------------
| cd98765432 | 10 | | 9 |
------------------------------------------
| ef24681357 | 11 | 13 | |
------------------------------------------
Remarquez que les cases vides peuvent être représentées par l’absence d’une valeur (comme pour la première case de la deuxième ligne) ou tout simplement omises dans le fichier CSV si elle apparaît en fin de ligne (comme la dernière case).
Exercice 2 : Manipulation de fichier CSV¶
On représente le contenu d’un fichier CSV par la liste de ces lignes. Une ligne est elle-même la liste de ses valeurs (des chaînes de caractères).
type csv_content = string list list
Définissez une fonction
input_lines : in_channel -> string listqui renvoie la liste des lignes du canal d’entrée passé en paramètre.Définissez une fonction
read_csv : string -> csv_contentqui lit et renvoie le contenu d’un fichier CSV dont le nom est passé en paramètre.Définissez une fonction
join : string -> string list -> stringtelle quejoin sep lconcatène les éléments delséparés par le séparateursep.Définissez une fonction
write_csv : csv_content -> string -> unittelle quewrite_css c nameécritcdans le fichier appelénamesous un format CSV.Définissez une fonction
max_list : int list -> int list -> int listqui renvoie une liste dont l’élément d’indiceiest le maximum des éléments du même indice dans les listes passées en paramètres. Si une des listes est plus petite que l’autre, on considère que les éléments manquants sont égaux à 0.Définissez une fonction
print_cell : int -> string -> unittelle queprint_cell n straffiche un espace, la chaînestrsurncaractères (on complète par des espaces si nécessaire), un espace et une barre. Par exemple,print_cell 5 "foo"affiche la chaîne" foo |".Définissez une fonction
print_line : int list -> string list -> unitqui affiche le contenu d’une ligne. La première liste correspond aux tailles des colonnes et la deuxième au contenu des cellules. Par exemple,print_line [5; 3] ["foo"; "bar"]affiche la chaîne"| foo | bar |".Définissez une fonction
print_csv : csv_content -> unitqui affiche le contenu d’un fichier CSV comme proposé dans l’exemple introductif.
Exercice 3 : Analyse d'un fichier CSV¶
On cherche à analyser des fichiers CSV dans un format particulier.
La première ligne contient des intitulés.
La deuxième ligne contient des coefficients (sauf pour la première cellule)
correspondant à la pondération d’un examen pour le calcul de la moyenne d’une UE.
Les lignes suivantes correspondent à des étudiants composés d’un identifiant
et d’un certain nombre de notes.
On cherche à obtenir le contenu d’un tel fichier comme un enregistrement data:
type student = {
id : string;
grades : float option list; (* None correspond à ABI *)
}
type data = {
header : string list;
coeff : float list;
students : student list;
}
Définissez une exception
Invalid_formatqui sera levée dès que le fichier analysé ne correspond pas aux spécifications.Définissez une fonction
parse_coeff : string list -> float listqui prend en paramètre la ligne correspondant aux coefficients et les convertit en flottant.Définissez une fonction
grades_from_strings : string list -> float option listqui prend en paramètre la liste des notes et les convertit en flottants si possible. Toute note que l’on ne peut convertir en flottant devient la valeurNone.Définissez une fonction
normalize_grade : int -> float option list -> float option listtelle quenormalize_grade n lrenvoie la listelcomplétée par des valeursNonepour qu’elle soit de taillen. Si la liste a une taille supérieure àn, on lève une exceptionInvalid_format.Définissez une fonction
parse_student : int -> string list -> studentqui prend en paramètres un nombre de notes attendues et une ligne correspondant à un étudiant. Elle renvoie la représentation de l’étudiant associée.Définissez une fonction
parse_csv : csv_content -> dataqui analyse le contenu d’un fichier CSV et en produit la représentation. Le nombre de notes attendues pour les étudiants est déduit du nombre de coefficients sur la deuxième ligne du fichier.
Exercice 4 : Modification d'un fichier CSV¶
On cherche maintenant à calculer la moyenne des étudiants présents dans un fichier CSV. Il faudra définir une fonction process_file : string -> string -> unit qui charge le contenu d’un fichier CSV, ajoute une colonne qui contient la moyenne de chaque étudiant, et l’écrit dans un nouveau fichier.
Définissez une fonction moyenne :
float list -> float option list -> floatqui prend en paramètres une liste des coefficients et une liste de notes pour renvoyer la moyenne pondérée de ces notes.Définissez une fonction
process_student : float list -> student -> string listqui prend en paramètres une liste de coefficients et un étudiant. Elle renvoie la ligne correspondant à l’étudiant. On y trouve son identifiant, ses notes (les valeursNonedeviennent"ABI") et sa moyenne.Définissez la fonction
process_filetelle queprocess_file name_in name_outlit le fichiername_inet écrit dans le fichiername_out. Par exemple, le code suivant
let () = process_file "exemple.csv" "moyenne.csv"
let () = print_csv (read_csv "moyenne.csv")
affiche
----------------------------------------------------
| Identifiant | Partiel | Projet | Final | Moyenne |
----------------------------------------------------
| | 0.3 | 0.3 | 0.4 | |
----------------------------------------------------
| ab12345678 | 12. | 15. | 14. | 13.7 |
----------------------------------------------------
| cd98765432 | 10. | ABI | 9. | 6.6 |
----------------------------------------------------
| ef24681357 | 11. | 13. | ABI | 7.2 |
----------------------------------------------------