IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage Perl Discussion :

Conseils pour correcteur orthographique


Sujet :

Langage Perl

  1. #1
    Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2013
    Messages
    3
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2013
    Messages : 3
    Points : 2
    Points
    2
    Par défaut Conseils pour correcteur orthographique
    Bonjour je dois créer un correcteur orthographique en perl qui doit effectuer quatre tâches différentes: l'insertion de caractères, la substitution, la suppression et la transposition. Puis mettre les corrections dans un nouveau fichier.

    Il doit aussi prendre en compte l'accentuation des mots, ce que je n'ai pas encore réussi à trouver pour le moment.

    De même pour l'insertion de caractère, il semble qu'un splice ne soit pas suffisant pour cette opération, car pour le mot mal orthographié "lou" il ne trouve pas le mot "loup" dans le dictionnaire.



    Voici donc mon code:


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
     
    #!/usr/bin/perl -w
     
    use strict;
    use utf8;
    binmode(STDOUT, ":encoding(utf8)");
    binmode(STDIN, ":encoding(utf8)");
     
    my $alphafr;
    my ($mot_errone, $ligne, $ligne1, $ligne2, $elt, $m, $transposition, $lettre1, $lettre2, $suppression,$insertion,$substitution, $choix,
    @mot, @mot_modifie, @fichier_dicfr, @texte, @dicfr, @insertion, @substitution, @transposition, @suppression, @propositions);
     
    my %ponctuation = (
    	' '   => 1,
    	''    => 1,
    	','   => 1,
    	"'"   => 1,
    	'.'   => 1,
    	'‒'   => 1,
    	';'   => 1,
    	'!'   => 1,
    	'-'   => 1,
    	':'   => 1,
    	'?'   => 1
    );
     
     
     
    #les mots du lexique sont stockés dans une tableau
    my $fichier_dicfr= "lexique.txt";
    open (LEXFR, "<:encoding(utf8)", $fichier_dicfr);
    while (defined ( $ligne = <LEXFR>)){
    	chomp $ligne;
    	@fichier_dicfr = split (/\s/, $ligne);
    	push (@dicfr, @fichier_dicfr);
    }
    close (LEXFR);
     
     
    print "Bonjour, quel est le nom du fichier à analyser ?\n";
     
    #entrée du fichier à corriger par l'utilisateur
    my $fichier = <STDIN>;
    chomp $fichier;
    open (FCHFR,"<:encoding(utf8)", $fichier);
     
    #création de la version corrigée
    my $fichier_corrige = "correction.txt";
    open (COR, ">:encoding(utf8)", $fichier_corrige);
     
     
    print "Voici les fautes repérées et mes suggestions de correction \n";
     
    while (defined ($ligne1 = <FCHFR>)) {
    	chomp $ligne1;
    	@texte = split (/(\pP|\pS|\s)/, lc $ligne1);
    	#Capture des mots non présents dans le lexique
    	for (my $i=0; $i < @texte; $i++) {
    		if (!grep (/^$texte[$i]$/, @dicfr) and not exists ($ponctuation{$texte[$i]})){
    			push (@mot, $texte[$i]);
    			$mot_errone = $texte[$i];
    			print "Ligne $. : L'orthographe du mot  $mot_errone est erronée\n";
    			print "Quelle correction souhaitez-vous appliquer ? (indiquez le chiffre, ou 0 si aucune correction ne vous convient)\n";{
    				#liste des mots non trouvés dans le lexique
    				foreach $m(@mot){
    					@mot_modifie = split (//, $m);
    					open (LEXFR, "<:encoding(utf8)", $fichier_dicfr);
    						while (defined ($ligne2 = <LEXFR>)){
    							chomp $ligne2;
    							@fichier_dicfr = split (/\s/, $ligne2);
    							push (@dicfr, @fichier_dicfr);
    						}
    						#Boucle pour la transposition lcou devient clou
    						for (my $i = 0; $i < $#mot_modifie; $i++){
    							@transposition = @mot_modifie;
    							$lettre1 = $transposition[$i];
    							$lettre2 = $transposition[$i+1];
    							$transposition [$i] = $lettre2;
    							$transposition [$i+1]= $lettre1;
    							$transposition = join "", @transposition;
    								if (grep (/^$transposition$/, @dicfr)){
    									push (@propositions, $transposition);
    								}
    						}
     
    						#Boucle pour la suppression hommme devient homme
     
    					foreach $elt (0..$#mot_modifie) {
    						@suppression = @mot_modifie;
    						splice (@suppression, $elt, 1);
    						$suppression = join "", @suppression;
    						if (grep (/^$suppression$/, @dicfr)){
    							push (@propositions, $suppression);
    						}
     
    						#Boucle pour l'insertion homm devient homme
     
    						foreach $alphafr ('a'..'z'){
    							@insertion= @mot_modifie;
    							splice (@insertion, $elt, 0, $alphafr);
    							$insertion = join "", @insertion;
    							if (grep (/^$insertion$/, @dicfr)){
    								push (@propositions, $insertion);
    							}
    						#Boucle pour la substitution lou devient cou
     
    							@substitution = @mot_modifie;
    							splice(@substitution, $elt, 1, $alphafr);
    							$substitution = join "", @substitution;
    							if (grep (/^$substitution$/, @dicfr)){
    									push (@propositions, $substitution);
    							}
    						}
    					}
     
    				}
    			}
    			#Affichage des propositions et choix de l'utilisateur
    			print "@propositions\n";
    			$choix =<STDIN>;
    			chomp $choix;
    			#Remplacement du mot mal orthographié dans la ligne correspondante 
    			$ligne1 =~s/$mot_errone/$propositions[$choix]/;
    		}	
    	}
    	#création du fichier corrigé
    	print (COR $ligne1);
    }
    close (LEXFR);
    close (FCHFR);
    close (COR);
    Fichiers attachés Fichiers attachés

  2. #2
    Rédacteur/Modérateur

    Avatar de Lolo78
    Homme Profil pro
    Conseil - Consultant en systèmes d'information
    Inscrit en
    Mai 2012
    Messages
    3 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Conseil - Consultant en systèmes d'information
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2012
    Messages : 3 612
    Points : 12 469
    Points
    12 469
    Billets dans le blog
    1
    Par défaut
    Hum, ce n'est pas un problème simple.

    Déjà, il faut tenir compte des différentes formes que prennent les mots (pluriel, féminin, conjugaisons, etc.). Il faut également tenir compte des accents, des nombres, des tirets et des apostrophes, etc. Cela peut être fait dans le lexique, mais ça alourdit considérablement ce lexique.

    Tu règles le problème des majuscules en mettant tout en minuscule, mais cela veut dire que tu ne verras pas une erreur comme les mots "angleterre" ou "allemagne" écrits sans la majuscule.

    Ensuite, trouver tous les mots qui ne figurent pas dans le lexique n'a rien de bien complexe (bien qu'il puisse y avoir des considérations de performance à prendre en ligne de compte), mais trouver les mots qui "ressemblent" pour proposer une correction possible est bien plus difficile. Il faut alors, d'une façon ou d'une autre, essayer de définir une forme de "distance" entre deux mots en fonction du nombre de lettres différentes et de leur ordre, afin de pouvoir proposer les mots du dictionnaire les moins distants des mots non trouvés dans le texte à analyser.

    En termes de performances, stocker les mots du dictionnaire dans une table de hachage est certainement une bien meilleure solution que dans un tableau, la recherche sera considérablement plus rapide.

    Il y a une discussion intéressante de ce problème dans le livre "Programming Pearls" (j'ai bien écrit "Pearls", ça n'a rien à voir avec le langage Perl), de Jon Bentley (chapitre 13). Ce bouquin peut être téléchargé gratuitement au format PDF (avec un filigrane assez gênant en bas de chaque page, mais, bon, pour suivre globalement la discussion, ça reste utilisable).

  3. #3
    Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2013
    Messages
    3
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2013
    Messages : 3
    Points : 2
    Points
    2
    Par défaut
    Tout d'abord merci pour vos conseils.

    Effectivement la lecture du tableau est assez fastidieux.

    Je vais voir ce que je peux faire pour mettre le lexique dans une table.

    Et merci pour la recommandation du livre


    EDIT:

    après chargement du lexique dans une table de hashage l'affichage est vraiment plus rapide

    Les seuls problèmes qu'il me reste à résoudre sont : l'accentuation, l'ajout de lettre à la fin du mot (bizarrement cela fonctionne pour le début mais pour la fin. J'obtient par exemple pour "lou" = "clou" ou "flou" mais pas "loup" ni "loué"


    Et j'aimerais savoir comment faire pour quand l'utilisateur entre "0" le mot considéré comme erroné reste tel quel dans la correction ( sûrement une histoire de condition ...)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    #!/usr/bin/perl
     
    use warnings;
    use strict;
    use utf8;
    binmode(STDOUT, ":encoding(utf8)");
    binmode(STDIN, ":encoding(utf8)");
     
    my $alphafr;
    my ($mot_errone, $ligne, $ligne1, $ligne2, $elt, $m, $transposition, $lettre1, $lettre2, $suppression,$insertion,$substitution, $choix,
    @mot, @mot_modifie,@texte, @insertion, @substitution, @transposition, @suppression, @propositions);
     
    my $n=0;
     
    my %lexique;
     
    #table de hash pour ne pas prendre ne compte la ponctuation et les espaces vides
    my %ponctuation = (
    	' '   => 1,
    	''    => 1,
    	','   => 1,
    	"'"   => 1,
    	'.'   => 1,
    	'‒'   => 1,
    	';'   => 1,
    	'!'   => 1,
    	'-'   => 1,
    	':'   => 1,
    	'?'   => 1
    );
     
    #les mots du lexique sont stockés dans une tableau
    my $fichier_dicfr= "lexique.txt";
    open (LEXFR, "<:encoding(utf8)", $fichier_dicfr);
    while (defined ( $ligne = <LEXFR>)){
    	chomp $ligne;
    	$lexique{$ligne} = 1;
    }
    close (LEXFR);
     
     
    print "Bonjour, quel est le nom du fichier à analyser ?\n";
     
    #entrée du fichier à corriger par l'utilisateur
    my $fichier = <STDIN>;
    chomp $fichier;
    open (FCHFR,"<:encoding(utf8)", $fichier);
     
    #création de la version corrigée
    my $fichier_corrige = "correction.txt";
    open (COR, ">:encoding(utf8)", $fichier_corrige);
     
     
    print "Voici les fautes repérées et mes suggestions de correction \n";
     
    while (defined ($ligne1 = <FCHFR>)) {
    	chomp $ligne1;
    	@texte = split (/(\pP|\pS|\s)/, $ligne1);
    	#Capture des mots non présents dans le lexique
    	for (my $i=0; $i < @texte; $i++) {
    		if (not exists ($lexique{$texte[$i]})and not exists($ponctuation{$texte[$i]})){
    			push (@mot, $texte[$i]);
    			$mot_errone = $texte[$i];
    			print "Ligne $. : L'orthographe du mot  $mot_errone est erronée\n";
    			print "Quelle correction souhaitez-vous appliquer ? (indiquez le chiffre, ou 0 si aucune correction ne vous convient)\n";{
    				#liste des mots non trouvés dans le lexique
    				foreach $m(@mot){
    					@mot_modifie = split (//, $m);
    					open (LEXFR, "<:encoding(utf8)", $fichier_dicfr);
    						while (defined ($ligne2 = <LEXFR>)){
    							chomp $ligne2;
    							$lexique{$ligne2} = 1;
    						}
    						@propositions=();
    						#Boucle pour la transposition lcou devient clou
    						for (my $i = 0; $i < $#mot_modifie; $i++){
    							@transposition = @mot_modifie;
    							$lettre1 = $transposition[$i];
    							$lettre2 = $transposition[$i+1];
    							$transposition [$i] = $lettre2;
    							$transposition [$i+1]= $lettre1;
    							$transposition = join "", @transposition;
    								if (exists ($lexique{$transposition})){
    									push (@propositions, $transposition);
    								}
    						}
     
    						#Boucle pour la suppression hommme devient homme
     
    					foreach $elt (0..$#mot_modifie) {
    						@suppression = @mot_modifie;
    						splice (@suppression, $elt, 1);
    						$suppression = join "", @suppression;
    						if (exists ($lexique{$suppression})){
    							push (@propositions, $suppression);
    						}
     
    						#Boucle pour l'insertion homm devient homme
     
    						foreach $alphafr ('a'..'z'){
    							@insertion= @mot_modifie;
    							splice (@insertion, $elt, 0, $alphafr);
    							$insertion = join "", @insertion;
    							if (exists ($lexique{$insertion})){
    								push (@propositions, $insertion);
    							}
    						#Boucle pour la substitution lou devient cou
     
    							@substitution = @mot_modifie;
    							splice(@substitution, $elt, 1, $alphafr);
    							$substitution = join "", @substitution;
    							if (exists ($lexique{$substitution})){
    									push (@propositions, $substitution);
    							}
    						}
    					}
     
    				}
    			}
    			#Affichage des propositions et choix de l'utilisateur
    			#$n++;
    			print "@propositions\n";
    			#$n=0;
    			$choix =<STDIN>;
    			chomp $choix;
    			#Remplacement du mot mal orthographié dans la ligne correspondante 
    			$ligne1 =~s/$mot_errone/$propositions[$choix]/;
    		}	
    	}
    	#création du fichier corrigé
    	print (COR $ligne1);
    }
    close (LEXFR);
    close (FCHFR);
    close (COR);

  4. #4
    Rédacteur/Modérateur

    Avatar de Lolo78
    Homme Profil pro
    Conseil - Consultant en systèmes d'information
    Inscrit en
    Mai 2012
    Messages
    3 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Conseil - Consultant en systèmes d'information
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2012
    Messages : 3 612
    Points : 12 469
    Points
    12 469
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par edensoul Voir le message

    Et j'aimerais savoir comment faire pour quand l'utilisateur entre "0" le mot considéré comme erroné reste tel quel dans la correction ( sûrement une histoire de condition ...)
    La substitution ne se fera pas quand l'utilisateur tape 0 si tu écris ta ligne de code comme ceci:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $ligne1 =~s/$mot_errone/$propositions[$choix]/ if $choix;
    Ainsi, la substitution ne se fait pas si $choix = 0 ou si choix n'est pas défini (vide).

    L'autre solution est de commencer par mettre le mot supposé erroné dans le tableau @propositions (comme premier élément du tableau), en sorte que $propositions[0] soit ce mot. Dans ce cas, si l'utilisateur tape 0, le mot erroné est remplacé par lui-même.

    Pour l'accentuation, je passe mon tour pour l'instant car je ne vois pas très bien quel est le problème. En général, je ne travaille que sur de l'ASCII 7 bits et je ne connais donc pas très bien les problématiques Unicode/UTF8/etc., mais je n'ai pas rencontré de difficulté particulière les quelques fois où j'ai eu besoin de comparer des textes et fichiers ayant des mots accentués: je suppose que les mots étant encodés de la même manière des deux côtés, le programme se débrouillait pour s'y retrouver. Ou alors, peut-être que ma machine ou mon installation de Perl était paramétrée correctement, avec le bon "locale" pour gérer les caractères accentués français, cédilles, etc. Il s'agissait d'un gros serveur sur lequel je n'ai aucun contrôle, l'installation de Perl a été faite à ma demande par un administrateur système, mais j'ignore ce qu'il a fait précisément.

    J'ai notamment eu besoin de valider des adresses mail (ou, plutôt, le contraire, de détecter des adresses invalides). La présence d'un caractère accentué était une cause d'exclusion. Je n'ai eu aucun problème à détecter des adresses de la forme "toto.titi@numéricable.fr" et à les remplacer par une version avec le même caractère non accentué avec une commande du genre : "tr/àéèùôç/aeeuoc/", pour obtenir: "toto.titi@numericable.fr"

    Par ailleurs, je viens de faire un petit essai sur mon PC perso avec Perl sous Cygwin, il a l'air de gérer tout aussi correctement les accents dans les cas simples. Par exemple, le code suivant:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    my $c = "caméra";
    print $c if $c =~ /(a|b)mér/;
    m'imprime bien "caméra". Donc, ma version de Perl semble s'arranger des accents aussi bien dans la chaîne de caractère contenue dans la variable $c que dans l'expression régulière /(a|b)mér/. Je parviens même à utiliser un caractère utiliser dans la clef d'un hash:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    $d{'caméra'} = "toto";
    print $d{'caméra'}
    fonctionne correctement, de même que:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    my $c = "caméra";
    $d{$c} = "toto";
    print $d{$c};
    Bref, je sais bien qu'il peut y avoir des problèmes avec les accents, en Perl comme dans d'autres langages, mais le pire n'est pas certain, il se peut que ça marche tout seul ou presque. Et si tu as eu des problèmes, explique leur nature.

  5. #5
    Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2013
    Messages
    3
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2013
    Messages : 3
    Points : 2
    Points
    2
    Par défaut
    Je vais opter pour la solution de mettre le mot erroné en première position dans le tableau, ce qui est plus cohérent avec l'énoncé.

    En ce qui concerne les accents c'est au niveau de l'insertion de lettres et de substitution que cela pose problème.

    $alphafr ( 'a'..'z' ) ne prend pas les accents. Je pense créer un tableau contenant les lettres de l'alphabet français, logiquement cela devrait résoudre le problème.

    EDIT1: j'ai résolu le problème d'insertion de caractère, il fallait rajouter +1 après $elt dans le splice

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    splice (@insertion, $elt+1, 0, $alphafr);
    Maintenant j'ai bien "loup" de proposer pour le mot "lou", il ne manque plus que les accents... affaire à suivre...

    EDIT2: mettre l'alphabet avec les accents dans un tableau à résolu le problème. Il me reste juste à changer le nom du fichier sortie pour plus de clarté "nomdufichier" - "corrigé" .txt

    Encore merci pour votre aide

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 5
    Dernier message: 14/03/2013, 15h29
  2. Recherche correcteur orthographique pour JSP
    Par meda dans le forum Servlets/JSP
    Réponses: 1
    Dernier message: 19/01/2010, 09h59
  3. Réponses: 11
    Dernier message: 03/09/2009, 23h45
  4. Utiliser les fichiers de syntaxe pour le correcteur orthographique avec vim
    Par karmaki dans le forum Applications et environnements graphiques
    Réponses: 2
    Dernier message: 11/08/2006, 06h01
  5. [web] Cherche un conseil pour un livre perl-tk
    Par Anonymous dans le forum Interfaces Graphiques
    Réponses: 2
    Dernier message: 29/04/2002, 15h35

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo