command line fuzzy logic

Fórumok

Melóhelyemen ki kéne bányásznom egy címjegyzék táblázatból azokat a postacímeket, amelyeknek rossz az irányítószáma. A rendszer Win, de feltettem egy MSys-t, hogy otthonosabban legyen.
Beszereztem a posta.hu irányítószám-jegyzékét, finomítás után átadtam a grep-nek, hogy ezeket a kifejezéseket keresse a címjegyzékben és ha valamelyik városhoz nem a megfelelő ir.szám tartozik, akkor azt írja ki. Jól is működne a dolog, ha nem lennének rövidítések, félregépelések a címjegyzékben... (-_-')
Ez miatt kéne egy progi, ami egy kis hibatűrést megenged ugyan, de azokat a részeket, amiket megadok (ir.szám), azt változatlan formában keresse a címjegyzékben. Találtam egy agrep nevezetűt, ami ígéretesnek tűnt, de hibaüzenettel kidob, ha megadom neki pl. a '-2' kapcsolót. Mivel win32 verziót nem találtam, ezért magam fordítottam le - lehet, hogy compile közben valami félresiklott, amit nem vettem észre. Grep-en kívül egyéb megoldás is érdekel, a lényeg, hogy legyen benne hibatűrés (fuzzy logic ?) és hogy képes legyen a keresési mintát fájlból venni.

Hozzászólások

Hirtelen a Levenshtein-távolság jut eszembe, de ehhez nem tudok kész megoldást. De szép gyakorló példa lenne. :))

--
Debian - The "What?!" starts not!
http://nyizsa.uni.cc

Nekem van kész kódom, csak C#-ban írtam annak idején. De kiindulási alapnak jó lehet:


        public static int LevenshteinDistance(string s, string t)
        {
            int[,] d = new int[s.Length + 1, t.Length + 1];

            for (int i = 0; i <= s.Length; i++)
                d[i, 0] = i;
            for (int j = 0; j <= t.Length; j++)
                d[0, j] = j;

            for (int j = 1; j <= t.Length; j++)
            {
                for (int i = 1; i <= s.Length; i++)
                {
                    if (s[i - 1] == t[j - 1])
                        d[i, j] = d[i - 1, j - 1];
                    else
                    {
                        d[i, j] = Math.Min(Math.Min(
                                     d[i - 1, j] + 1,
                                     d[i, j - 1] + 1),
                                     d[i - 1, j - 1] + 1);
                    };
                }
            }

            return d[s.Length, t.Length];
        }

jaja, igen, a levenshtein az jo lenne. unix alatt konnyu osszeherkenteni, de ha van win alatt cygwin-ed, akkor kb ugyanolyan konnyu lehet. shell+awk kombinacioban pl ennyi az egesz:


function levenshtein_distance()
{
 echo "$1" "$2" | \
 awk \
  '{    s=$1;m=length(s); 
        t=$2;n=length(t); 
        for ( i=0 ; i<=m ; i++ ) 
                d[i*(n+1)+1]=i; 
        for ( j=0 ; j<=n ; j++ ) 
                d[j+1]=j; 
 
        for ( j=1 ; j<=n ; j++ ) 
         {      for ( i=1 ; i<=m ; i++ ) 
                 {      if ( substr(s,i,1) == substr(t,j,1) ) 
                                d[i*(n+1)+j+1]=d[(i-1)*(n+1)+j]; 
                        else 
                         {      m1=d[(i-1)*(n+1)+j+1]+1; 
                                m2=d[i*(n+1)+j]+1; 
                                m3=d[(i-1)*(n+1)+j]+1; 
                                mm=m1; 
                                if ( m2<m )     mm=m2; 
                                if ( m3<m )     mm=m3; 
                                d[i*(n+1)+j+1]=mm; 
                         } 
                 } 
         } 
        print d[(m+1)*(n+1)]; 
  }'
}

levenshtein_distance $1 $2

(es akkor ezt a `levenshtein_distance` valamit mint "programot" tudod ma'r hasznalni, egy ciklusban).

Ékezetesen kell csinálnod, az egyszer tuti (lásd Komló - Kömlő, ezzel anno még a nagy kéknek is meggyűlt a baja...) Egyébként rejtett subs :)

subscribe

------------------------------------------
Egyetlen vi-parancsot ismerek, a kilépést.