Série 4 – Diagrammes tige et feuille
Introduction
Le but de cette série est de visualiser, au moyen de diagrammes tige et feuille, la distribution des heures des rendus acceptés par notre serveur pour les quatre premières étapes du projet. La construction de ces diagrammes constitue un bon exemple d'utilisation des tables associatives et des listes.
Un diagramme tige et feuille (stem-and-leaf plot, souvent abrégé stemplot en anglais) permet de visualiser la distribution d'un ensemble de valeurs entières. Il est similaire à un histogramme à barres horizontales, mais dont les barres sont les chiffres des unités des valeurs elle-mêmes.
Par exemple, admettons l'existence d'une équipe de 14 jeunes sportifs dont la taille en centimètres est { 152, 152, 154, 160, 161, 161, 162, 163, 163, 173, 173, 175, 175, 191 }. Pour créer un diagramme tige et feuille à partir de ces données, on commence par séparer chaque valeur en une tige, composée de tous les chiffres sauf celui des unités, et une feuille, le chiffre des unités. Par exemple, la valeur 152 a pour tige 15 et pour feuille 2, tandis que la valeur 154 a également 15 comme tige mais 4 comme feuille. Cette séparation faite, on produit le diagramme en affichant une ligne par tige possible entre la plus petite et la plus grande tige trouvées dans les données. Chaque ligne est composée de la tige qui lui correspond, suivie d'une barre verticale et de toutes les feuilles ayant cette tige, triées en ordre croissant. Pour les valeurs données plus haut, on obtient le diagramme suivant :
15|224 16|011233 17|3355 18| 19|1
Un tel diagramme permet d'une part de visualiser la distribution des données, puisque la longueur de chaque ligne est proportionnelle au nombre de valeurs ayant la tige correspondant à la ligne, et d'autre part de connaître précisément les valeurs présentes dans les données. Ainsi, au moyen du diagramme ci-dessus, il est trivial de reconstituer la totalité des données.
Il est également possible de construire des diagrammes tige et feuille bidirectionnels, permettant de comparer les distributions de deux ensembles de valeurs. Par exemple, admettons que les hauteurs des jeunes sportifs données plus haut soient celles de 8 filles de hauteurs { 152, 152, 160, 161, 163, 173, 175, 175 } et 6 garçons de hauteurs { 154, 161, 162, 163, 173, 191 }. On peut représenter ces deux ensembles de données au moyen du diagramme bidirectionnel suivant, les filles étant à gauche et les garçons à droite :
22|15|4 310|16|123 553|17|3 |18| |19|1
Squelette
Pour démarrer, nous vous fournissons une archive Zip contenant :
- quatre fichiers de données (
stage-1.txt
àstage-4.txt
) dans le répertoiredata
, contenant les dates et heures des rendus acceptés par notre serveur de rendu pour les étapes 1 à 4, - une classe
TimestampReader
permettant de lire ces fichiers de données, - une classe
Main
lisant un fichier de données et l'affichant à l'écran, - un squelette de classe
StemPlot
représentant un diagramme tige et feuille, à compléter.
Importez le contenu de cette archive dans un nouveau projet Eclipse, et ajoutez-y le répertoire data
comme répertoire source, en suivant les indications données en bas de notre guide d'importation dans Eclipse.
Une fois cela fait, vous devriez pouvoir exécuter la méthode main
de la classe Main
et voir s'afficher à l'écran la liste des heures de rendu de l'étape 1, sous forme d'entiers (voir plus bas pour leur format) :
[172, 172, 172, 172, 172, 171, 171, 171, 171, …
Si vous obtenez une exception, vérifiez que vous avez bien ajouté le répertoire data
comme répertoire source, comme expliqué ci-dessus.
Exercice 1 : Diagramme unidirectionnel
Le but du premier exercice est de compléter la méthode print
de la classe StemPlot
, permettant d'afficher un diagramme tige et feuille unidirectionnel.
Méthode print
La méthode print
prend en argument une collection d'entiers supposés positifs et affiche le diagramme tige et feuille correspondant.
Pour afficher ce diagramme, nous vous conseillons de construire une table associative de type Map<Integer, List<Integer>>
associant à chaque tige (un entier) la liste de ses feuilles (des entiers à un seul chiffre), triées par ordre croissant. Une fois cette table construite, l'affichage du diagramme est relativement simple.
Dans un premier temps, contentez-vous d'écrire la méthode print
de la manière qui vous semble la plus naturelle, et vérifiez qu'elle fonctionne en dessinant le diagramme tige et feuille correspondant au rendu de l'étape 1.
Notez que la méthode hours
de la classe Main
que nous vous fournissons, qui transforme les heures en entiers à dessiner sous forme de diagramme tige et feuille, représente les heures au moyen d'entiers compris entre 0 et 235. Les deux premiers chiffres représentent l'heure, le dernier la dizaine de minutes. Par exemple, 16h57 est représenté par l'entier 165.
Alignement des tiges
La méthode print
que vous avez écrite présente probablement le problème suivant : les tiges ne sont pas toutes alignées, car certaines font un caractère de large, d'autres deux. Dans ce cas, les lignes des tiges 9 et 10 se présentent ainsi :
9|01115 10|12334455
Pour résoudre ce problème d'alignement, le plus simple est d'utiliser la méthode format
de la classe String
. Cette méthode permet de formatter différents types de données sous forme de chaîne de caractères et prend un nombre variable d'arguments :
- le premier est la chaîne de formattage, qui contient un mélange de texte libre et de séquences de formattage, commençant chacune par le caractère pourcent (
%
) et destinées à être remplacées par une donnée formattée, - les suivants (un par séquence de formattage présente dans la chaîne de formattage) sont les données à insérer.
Le format de la chaîne de formattage est bien documenté mais assez complexe. Toutefois, l'alignement des tiges peut se faire très simplement, comme l'exemple ci-dessous l'illustre :
String s1 = String.format("%2d", 9); // " 9" String s2 = String.format("%2d", 10); // "10"
Les deux chaînes s1
et s2
font deux caractères, mais la première commence par une espace afin justement que le nombre qu'elle formatte ait une largeur de deux caractères. Ce comportement est dû à la chaîne de formattage passée (%2d
), qui spécifie que :
- la prochaine valeur (
%
), - doit être formattée sur deux caractères (
2
), - sous la forme d'un entier décimal (
d
).
Inspirez-vous de cet exemple pour aligner correctement les tiges.
Utilisation de computeIfAbsent
Pour terminer cet exercice, essayez de rendre votre méthode print
plus concise en vous aidant de la méthode computeIfAbsent
de l'interface Map
, qui n'a pas été examinée au cours mais dont vous devriez pouvoir comprendre le fonctionnement en lisant sa documentation.
Exercice 2 : Diagramme bidirectionnel
Ajoutez à la classe StemPlot
une seconde variante de la méthode print
prenant deux collections d'entiers en arguments et dessinant un diagramme tige et feuille bidirectionnel avec ces données.
Pour que les feuilles de la partie gauche fassent toutes la même longueur, vous pouvez une fois de plus utiliser la méthode format
de la classe String
, en vous inspirant de l'extrait de programme suivant :
String s1 = String.format("%5s", "ah"); // " ah" String s2 = String.format("%5s", "bon"); // " bon"
Notez que cette fois la chaîne de formattage utilise un s
(pour string) à la place du d
(pour decimal) utilisé plus haut, car ici la donnée à formatter est une chaîne de caractères.
N'hésitez pas, dans un premier temps en tout cas, à utiliser une largeur fixe de 30 caractères (p.ex.) pour aligner les feuilles de la partie gauche du diagramme.
Une fois votre méthode terminée, testez-la en dessinant un diagramme tige et feuille bidirectionnel pour les heures de rendu des étapes 3 et 4, par exemple.