Bonjour,
Je tiens à vous prévenir : les termes que j'emploierai dans ce message (et ceux employés dans son sujet) sembleront probablement incorrects aux yeux des puristes mais je fais ce que je peux avec mon vocabulaire plus que limité.
Afin que chacun puisse comprendre, j'essaierai d'expliquer ce que j'entends par "ambiguïté", "expression rationnelle", 'collision" (voir plus loin), et autres.
Afin que je puisse vous comprendre, vous avez le choix : soit vous utilisez mes termes, soit vous définissez ceux que vous utilisez d'une façon facilement compréhensible pour un non initié (et non puriste).
Première chose : quand j'écris "expression rationnelle" (dans ce message) je parle de ce que d'autres appellent "expressions régulières" ("regular expressions" en anglais).
Il s'agit d'expressions telles que celles utilisées par les commandes grep et sed.
Voyez http://etna.int-evry.fr/COURS/UNIX/f...n1/grep.1.html si vous n'êtes pas sûrs de savoir de quoi je parle.
Il est fortement probable que j'utilise les termes "expression régulière", "expression", ou "regex" pour désigner une (i.e. en lieu et place de) "expression rationnelle".
Cette première mise au point étant faite, passons à mon but...
Les regex sont souvent utilisées pour "filtrer" du texte : on donne à un programme (comme grep ou sed) du texte et une expression régulière et le programme effectue un traitement (affichage, modification) sur les parties du texte qui correspondent (ou pas) à l'expression régulière fournie.
Dans ces cas, on fournit une regex et des données en entrée à un programme.
Ce que je souhaite faire, c'est "l'inverse". Je veux fournir une expression à un programme et je veux qu'il me fournisse des données en sortie (sans autre entrée que l'expression) : je veux écrire un programme qui, étant donné une regex, génère toutes les chaînes de caractères qui correspondent à cette dernière.
A noter que le sujet de ce message n'est pas de discuter de l'utilité d'un tel programme, mais de discuter de comment l'écrire.
Exemples :
1) je fournis "[01]" (sans les guillemets) à mon programme et il me donne "0" puis "1", soit les chaînes composées d'un caractère pris parmi "0" ou "1" (vous noterez que je n'utilise pas les méta-caractères "^" et "$").
2) pour "abc{3,5}", le programme écrit "abccc" puis "abcccc" puis "abccccc", soit les chaînes composées d'un "a" suivi d'un "b" suivi de 3 à 5 "c".
3) pour "[A-E][0-9]", le programme écrit "A0", "A1", ... "A9", "B0", "B1", ... "B9", ... "E9", soit les chaînes composées d'un caractère parmi "A" ou "B" ou "C" ou "D" ou "E" suivi par un caractère parmi les chiffres de "0" à "9".
4) pour "[A-Z]{3,10}[0-9]{5,9}", le programme écrit les chaînes composées d'une suite de 3 à 10 lettres majuscules suivie d'une suite de 5 à 9 chiffres de "0" à "9".
Vous suivez toujours ?
Enchaînons sur mon problème : certaines expressions sont, selon mes termes, "ambigües".
Commençons par un exemple : considérez l'expression "[AB01]{3,10}[01]{5,9}".
Elle doit permettre de générer toutes les chaînes composées de 3 à 10 caractères pris parmi "A" ou "B" ou "0" ou "1" suivis de 5 à 9 caractères pris parmi "0" ou "1".
Vous noterez que j'ai écrit mon expression en utilisant deux couleurs : le but est de faire ressortir le fait que cette expression peut être découpée en deux sous-expressions plus simples et de mieux vous faire comprendre d'où vient mon problème.
Quand mon programme génère les chaînes correspondantes, il génère en fait les chaînes formées par la concaténation des chaînes générées par les deux sous-expressions.
Note: dans ce qui suit j'utiliserai "expansion d'une expression" pour désigner "la génération de toutes les chaînes de caractères formées en suivants les règles de génération énoncées par l'expression".
Donc, l'expansion de l'expression donnée en exemple se fait par concaténation de chaque chaîne générée par expansion de la première sous-regex avec chacune des chaînes résultant de l'expansion de la deuxième sous-regex.
Par exemple, parmi les chaînes générées on trouvera :
"ABBA00100110"
"BBAABA111100110"
Mais on trouvera aussi :
"ABBA00100110"
"BBAABA111100110"
Voilà mon problème : mon programme génère des doublons.
C'est pour cette raison que je qualifie mon expression d'ambigüe : par expansions différentes des sous expressions qui la composent, on obtient des résultats identiques.
Autrement dit : un même résultat peut être obtenu de deux façons (ou plus) différentes (c'est dans ce cadre que je parle de "collision").
Je ne veux pas filtrer ce qui sort de mon programme pour éliminer les doublons : je veux que mon programme n'en produise pas.
D'ailleurs, dans la pratique, filtrer les doublons après coup risque de trouver ses limites : grosse consommation de mémoire, perte de temps, etc.
Ce que je pensais faire peut être résumé ainsi : transformer l'expression de départ en une ou plusieurs expressions "non ambigües" de telle façon que les chaînes générées à partir de ces expressions soient les mêmes que celles qui auraient été obtenue par expansion de l'expression de départ mais sans les doublons.
Par exemple, soit une expression E0 telle que E0="[AB01]{3,10}[01]{5,9}". J'aurai (si ce que je souhaite est possible) : E0="[AB01]{2,9}[AB][01]{5,9}|E1" avec E1 une autre expression à déterminer (et "|" dénotant une alternative, un "OU" si vous préférez).
Comment trouver "E1" ?
J'espère avoir réussi à expliquer mon problème de façon compréhensible.
Evidemment, je préfèrerai obtenir des réponses qui soient plus détaillées et compréhensibles qu'un simple "t'as qu'à lire le théorème de Truc et l'appliquer à la conjecture Muche dans les cas ou la condition de Bidule est réalisée"
Merci pour votre attention.
Partager