Anagrammes des mots du dictionnaire |
Écrire un programme Ana qui trouve toutes les anagrames présentes dans un dictionnaire.
Plus précisément, si le dictionnaire petit.txt est constitué des mots apéros, broutera, chenil, lichen, narval, obturera, opéras, outre, paréos, raboteur, rabouter, et raton-laveur, alors la commande « java Ana petit.txt » produit l'affichage suivant :
rabouter raboteur obturera broutera lichen chenil paréos opéras apéros
On observe que chaque ligne regroupe les anagrammes, et que les mots isolés (ici outre, narval et raton-laveur) ont disparu.
Le défi est de traiter des dictionnaires comportant jusqu'à cent mille mots. Bien que cela puisse paraître difficile à première vue, c'est tout à fait faisable (et c'est aussi assez classique).
La suite décrit deux techniques possibles de production des anagrammes. Il est demandé d'implémenter au moins une des deux techniques, voire les deux si vous en avez le courage.
Dans tous les cas, il faut tester votre programme sur les dictionnaires fournis plus bas.
Il est inutile de rédiger un rapport, je suis prêt à me contenter du graphique légèrement commenté.
À chaque mot, on associe une signature qui est telle que deux mots ont la même signature si et seulement si ils sonts anagrammes l'un de l'autre (ou encore un mot s'obtient par permutation des lettres de l'autre).
Un telle signature s'obtient en triant les lettres des mots. Par exemple, lichen et chenil sont des anagrammes parce que leur signature cehiln est la même.
Pour fabriquer les signatures le plus simple est de produire un
tableau de char
(méthode
char [] toCharArray()
de la classe
String
), de trier le
tableau (à vous de jouer !), puis de fabriquer une chaîne avec le
tableau
(constructeur String (char [] value)
)).
Trouver les anagrammes revient donc à regrouper les mots qui ont la même signature. On y arrive en triant et en trois temps.
String
par s1.compareTo(s2) qui renvoie
−1 si s1 est plus petit que s2, 0 si s1 est égal à s2,
et 1 si s1 est plus grand que s2 (cf. la méthode
compareTo
).On se donne une table de hachage dont les clés sont les signatures
(donc des String
) et les valeurs des listes de mots (donc des
listes de String
). Tous les mots d'une liste donnée ont la même
signature et la table associe la liste à cette signature commune.
L'algorithme procède en deux temps.
Votre programme doit prendre le nom du fichier-dictionnaire en argument et afficher les anagrammes. Rassurez vous, tout le code nécessaire pour lire les fichiers dictionnaires est donné ci-dessous.
Un exemple d'exécution est donc
% java Ana /usr/share/dict/words cleansing cleanings ushers rushes smitten mittens racing caring arcing diuretics crudities breaks brakes bakers ...
L'ordre de présentation des anagrammes n'est pas spécifié et votre programme peut très bien avoir un affichage différent. Pour savoir si votre programme fonctionne comme le mien, vous pouvez compter les lignes et les mots du fichier produit ainsi :
% java Ana ./petit.txt | wc 3 9 71 % java Ana ./moyen.txt | wc 448 1000 9090 % java Ana ./francais.txt | wc 8378 18515 168057
Le tuyau (pipe, noté « | ») connecte la sortie standard d'une commande Unix avec l'entrée standard de la suivante. La commande wc compte les lignes, les mots et les caractères d'un fichier.
Voici quelques dictionnaires.
% java Ana /usr/share/dict/words
Les dictionnaires sont des fichiers dont chaque ligne est un mot.
Je fournis le code d'une classe des lecteurs de mots
(WordReader
) suffisante pour lire ce genre de dictionnaires.
Cette classe est conforme au modèle décrit lors de
l'amphi 04.
Par ailleurs, la classe elle-même comporte une méthode main
qui donne un exemple d'utilisation (recopier le dictionnaire dans
la sortie standard).
Ce document a été traduit de LATEX par HEVEA