File Coverage

blib/lib/Text/Phonex.pm
Criterion Covered Total %
statement 88 95 92.6
branch 2 4 50.0
condition 2 5 40.0
subroutine 5 7 71.4
pod 0 3 0.0
total 97 114 85.0


line stmt bran cond sub pod time code
1             # -*- coding: UTF-8 -*-
2             package Text::Phonex;
3 1     1   27654 use Carp;
  1         3  
  1         102  
4 1     1   6 use strict;
  1         2  
  1         39  
5             # $Id: Phonex.pm 429 2009-10-14 14:18:53Z gab $
6             BEGIN {
7 1     1   5 use Exporter;
  1         7  
  1         201  
8 1     1   3 our ($VERSION, @ISA, @EXPORT, @EXPORT_OK );
9 1         14 @ISA=qw(Exporter);
10 1         3 @EXPORT=qw( phonex );
11 1         1359 $VERSION='0.04';
12             sub VERSION {
13 0     0 0 0 (my $me, my $askedver)=@_;
14 0         0 $VERSION=~s/(.*)_\d+/$1/;
15 0 0       0 croak "Please update: $me is version $VERSION and you asked version $askedver" if ($VERSION < $askedver);
16             }
17             }
18              
19             #Origine : Algorithme Phonex de Frédéric BROUARD (31/3/99)
20             #Source : http://sqlpro.developpez.com/cours/soundex
21             #Version Python : Christian Pennaforte - 5 avril 2005
22             #Suite : Florent Carlier
23             #Perl version : Gabriel Guillon
24             sub new {
25 0     0 0 0 my $this = shift;
26 0   0     0 my $class = ref($this) || $this;
27 0         0 my $self=\&phonex;
28 0         0 bless $self, $class;
29             }
30             sub phonex {
31 9     9 0 26 my $chaine=shift;
32 9   100     40 my $precision=shift || 15;
33             #0 On met la chaîne en majuscules, on vire les caractères parasites
34 9         22 $chaine =~ tr/àâäãéèêëìîïòôöõùûüñ/AAAAYYYYIIIOOOOUUUN/;
35 9         48 $chaine =~ s/[ -\.\+\*\/,:;_]//g;
36 9         21 $chaine = uc($chaine);
37              
38             #1 remplacer les y par des i
39 9         15 $chaine=~s/Y/I/g;
40              
41             #2 supprimer les h qui ne sont pas précédées de c ou de s ou de p
42 9         21 $chaine =~ s/([^P|C|S])H/$1/g;
43              
44             #3 remplacement du ph par f
45 9         14 $chaine=~s/PH/F/g;
46              
47             #4 remplacer les groupes de lettres suivantes :
48 9         17 $chaine=~s/G(AI?[N|M])/K$1/g;
49              
50             #5 remplacer les occurrences suivantes, si elles sont suivies par une lettre a, e, i, o, ou u :
51 9         15 $chaine =~ s/[A|E]I[N|M]([A|E|I|O|U])/YN$1/g;
52              
53             #6 remplacement de groupes de 3 lettres (sons 'o', 'oua', 'ein') :
54 9         16 $chaine=~s/EAU/O/g;
55 9         12 $chaine=~s/OUA/2/g;
56 9         13 $chaine=~s/EIN/4/g;
57 9         14 $chaine=~s/AIN/4/g;
58 9         14 $chaine=~s/EIM/4/g;
59 9         12 $chaine=~s/AIM/4/g;
60              
61             #7 remplacement du son É:
62 9         11 $chaine=~s/É/Y/g; #CP : déjà fait en étape 0
63 9         12 $chaine=~s/È/Y/g; #CP : déjà fait en étape 0
64 9         15 $chaine=~s/Ê/Y/g; #CP : déjà fait en étape 0
65 9         18 $chaine=~s/AI/Y/g;
66 9         11 $chaine=~s/EI/Y/g;
67 9         22 $chaine=~s/ER/YR/g;
68 9         14 $chaine=~s/ESS/YS/g;
69 9         17 $chaine=~s/ET/YT/g; #CP : différence entre la version Delphi et l'algo
70 9         12 $chaine=~s/EZ/YZ/g;
71              
72             #8 remplacer les groupes de 2 lettres suivantes (son â..anâ.. et â..inâ..), sauf sâ..il sont suivi par une lettre a, e, i o, u ou un son 1 à 4 :
73 9         12 $chaine=~s/AN([^A|E|I|O|U|1|2|3|4])/1$1/g;
74 9         11 $chaine=~s/ON([^A|E|I|O|U|1|2|3|4])/1$1/g;
75 9         11 $chaine=~s/AM([^A|E|I|O|U|1|2|3|4])/1$1/g;
76 9         17 $chaine=~s/EN([^A|E|I|O|U|1|2|3|4])/1$1/g;
77 9         13 $chaine=~s/EM([^A|E|I|O|U|1|2|3|4])/1$1/g;
78 9         14 $chaine=~s/IN([^A|E|I|O|U|1|2|3|4])/4$1/g;
79              
80             #9 remplacer les s par des z sâ..ils sont suivi et précédés des lettres a, e, i, o,u ou dâ..un son 1 à 4
81 9         51 $chaine=~s/([A|E|I|O|U|Y|1|2|3|4])S([A|E|I|O|U|Y|1|2|3|4])/$1Z$2/g;
82             #CP : ajout du Y à la liste
83              
84             #10 remplacer les groupes de 2 lettres suivants :
85 9         14 $chaine=~s/OE/E/g;
86 9         10 $chaine=~s/EU/E/g;
87 9         14 $chaine=~s/AU/O/g;
88 9         12 $chaine=~s/OI/2/g;
89 9         10 $chaine=~s/OY/2/g;
90 9         16 $chaine=~s/OU/3/g;
91              
92             #11 remplacer les groupes de lettres suivants
93 9         14 $chaine=~s/CH/5/g;
94 9         11 $chaine=~s/SCH/5/g;
95 9         10 $chaine=~s/SH/5/g;
96 9         13 $chaine=~s/SS/S/g;
97 9         10 $chaine=~s/SC/S/g; #CP : problème pour PASCAL, mais pas pour PISCINE ?
98              
99             #12 remplacer le c par un s s'il est suivi d'un e ou d'un i
100             #CP : à mon avis, il faut inverser 11 et 12 et ne pas faire la dernière ligne du 11
101 9         22 $chaine=~s/C([E|I])/S$1/g;
102              
103             #13 remplacer les lettres ou groupe de lettres suivants :
104 9         16 $chaine=~s/C/K/g;
105 9         16 $chaine=~s/Q/K/g;
106 9         13 $chaine=~s/QU/K/g;
107 9         11 $chaine=~s/GU/K/g;
108 9         10 $chaine=~s/GA/KA/g;
109 9         13 $chaine=~s/GO/KO/g;
110 9         12 $chaine=~s/GY/KY/g;
111              
112             #14 remplacer les lettres suivante :
113 9         27 $chaine=~s/A/O/g;
114 9         10 $chaine=~s/D/T/g;
115 9         13 $chaine=~s/P/T/g;
116 9         14 $chaine=~s/J/G/g;
117 9         10 $chaine=~s/B/F/g;
118 9         27 $chaine=~s/V/F/g;
119 9         15 $chaine=~s/M/N/g;
120              
121             #15 Supprimer les lettres dupliquées
122 9         15 my $oldc='#';
123 9         11 my $newr='';
124 9         50 foreach my $c (split(//,$chaine)) {
125 147 100       233 $newr.=$c if ($oldc ne $c);
126 147         162 $oldc=$c;
127             }
128 9         27 $chaine = $newr;
129              
130             #16 Supprimer les terminaisons suivantes : t, x
131 9         121 $chaine=~s/(.*)[T|X]$/$1/g;
132              
133             #17 Affecter à chaque lettre le code numérique correspondant en partant de la dernière lettre
134 9         11 my $num = '12345EFGHIKLNORSTUWXYZ';
135 9         10 my @l;
136 9         37 foreach my $c (split(//,$chaine)) {
137 133         180 push @l, (index($num,$c));
138             }
139             #18 Convertissez les codes numériques ainsi obtenu en un nombre de base 22 exprimé en virgule flottante.
140 9         24 my $res=0;
141 9         10 my $i=1;
142 9         16 foreach my $n (@l) {
143 133         241 $res = $n*22**-$i+$res;
144 133         136 $i++;
145             }
146 9         124 return sprintf("%.${precision}f",$res);
147             }
148             1;