Levenshtein Uzaklığı


40

Gibi birçok düzenleme mesafe soruları, Varken bu bir , Levenshtein mesafeyi hesaplayan bir program yazmaya basit bir soru yoktur.

Bazı Fuar

İki kelime arasındaki Levenshtein düzenleme mesafesi , bir kelimeyi başka bir kelimeye dönüştürmek için mümkün olan minimum ekleme, silme veya değiştirme sayısıdır. Bu durumda, her ekleme, silme ve değiştirme işleminin maliyeti 1'dir.

Örneğin rollve arasındaki mesafe rolling3'tür, çünkü silmelerin maliyeti 1'dir ve 3 karakterin silinmesi gerekir. İkameler 1 olduğu için tollve arasındaki mesafe tall1'dir.

kurallar

  • Giriş iki karakter olacaktır. Dizelerin küçük harf olduğunu, yalnızca harf içerdiğini, boş olmadığını ve maksimum 100 karakter uzunluğunda olduğunu varsayabilirsiniz.
  • Çıktı, yukarıda tanımlandığı gibi iki dizenin minimum Levenshtein düzenleme mesafesi olacaktır.
  • Kodunuz bir program veya fonksiyon içermelidir. Adlandırılmış bir işlev olması gerekmez, ancak doğrudan Levenshtein mesafesini hesaplayan yerleşik bir işlev olamaz. Diğer yapılara izin verilir.
  • Bu kod golf, bu yüzden en kısa cevap kazanır.

Bazı örnekler

>>> lev("atoll", "bowl")
3
>>> lev("tar", "tarp")
1
>>> lev("turing", "tarpit")
4
>>> lev("antidisestablishmentarianism", "bulb")
27

Her zaman olduğu gibi, sorun açık değilse, lütfen bana bildirin. İyi şanslar ve iyi golf!

Katalog

var QUESTION_ID=67474;var ANSWER_FILTER="!t)IWYnsLAZle2tQ3KqrVveCRJfxcRLe";var COMMENT_FILTER="!)Q2B_A2kjfAiU78X(md6BoYk";var OVERRIDE_USER=47581;var answers=[],answers_hash,answer_ids,answer_page=1,more_answers=true,comment_page;function answersUrl(index){return"http://api.stackexchange.com/2.2/questions/"+QUESTION_ID+"/answers?page="+index+"&pagesize=100&order=desc&sort=creation&site=codegolf&filter="+ANSWER_FILTER}function commentUrl(index,answers){return"http://api.stackexchange.com/2.2/answers/"+answers.join(';')+"/comments?page="+index+"&pagesize=100&order=desc&sort=creation&site=codegolf&filter="+COMMENT_FILTER}function getAnswers(){jQuery.ajax({url:answersUrl(answer_page++),method:"get",dataType:"jsonp",crossDomain:true,success:function(data){answers.push.apply(answers,data.items);answers_hash=[];answer_ids=[];data.items.forEach(function(a){a.comments=[];var id=+a.share_link.match(/\d+/);answer_ids.push(id);answers_hash[id]=a});if(!data.has_more)more_answers=false;comment_page=1;getComments()}})}function getComments(){jQuery.ajax({url:commentUrl(comment_page++,answer_ids),method:"get",dataType:"jsonp",crossDomain:true,success:function(data){data.items.forEach(function(c){if(c.owner.user_id===OVERRIDE_USER)answers_hash[c.post_id].comments.push(c)});if(data.has_more)getComments();else if(more_answers)getAnswers();else process()}})}getAnswers();var SCORE_REG=/<h\d>\s*([^\n,<]*(?:<(?:[^\n>]*>[^\n<]*<\/[^\n>]*>)[^\n,<]*)*),.*?(\d+)(?=[^\n\d<>]*(?:<(?:s>[^\n<>]*<\/s>|[^\n<>]+>)[^\n\d<>]*)*<\/h\d>)/;var OVERRIDE_REG=/^Override\s*header:\s*/i;function getAuthorName(a){return a.owner.display_name}function process(){var valid=[];answers.forEach(function(a){var body=a.body;a.comments.forEach(function(c){if(OVERRIDE_REG.test(c.body))body='<h1>'+c.body.replace(OVERRIDE_REG,'')+'</h1>'});var match=body.match(SCORE_REG);if(match)valid.push({user:getAuthorName(a),size:+match[2],language:match[1],link:a.share_link,});else console.log(body)});valid.sort(function(a,b){var aB=a.size,bB=b.size;return aB-bB});var languages={};var place=1;var lastSize=null;var lastPlace=1;valid.forEach(function(a){if(a.size!=lastSize)lastPlace=place;lastSize=a.size;++place;var answer=jQuery("#answer-template").html();answer=answer.replace("{{PLACE}}",lastPlace+".").replace("{{NAME}}",a.user).replace("{{LANGUAGE}}",a.language).replace("{{SIZE}}",a.size).replace("{{LINK}}",a.link);answer=jQuery(answer);jQuery("#answers").append(answer);var lang=a.language;lang=jQuery('<a>'+lang+'</a>').text();languages[lang]=languages[lang]||{lang:a.language,lang_raw:lang.toLowerCase(),user:a.user,size:a.size,link:a.link}});var langs=[];for(var lang in languages)if(languages.hasOwnProperty(lang))langs.push(languages[lang]);langs.sort(function(a,b){if(a.lang_raw>b.lang_raw)return 1;if(a.lang_raw<b.lang_raw)return-1;return 0});for(var i=0;i<langs.length;++i){var language=jQuery("#language-template").html();var lang=langs[i];language=language.replace("{{LANGUAGE}}",lang.lang).replace("{{NAME}}",lang.user).replace("{{SIZE}}",lang.size).replace("{{LINK}}",lang.link);language=jQuery(language);jQuery("#languages").append(language)}}
body{text-align:left!important}#answer-list{padding:10px;width:290px;float:left}#language-list{padding:10px;width:290px;float:left}table thead{font-weight:700}table td{padding:5px}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <link rel="stylesheet" type="text/css" href="//cdn.sstatic.net/codegolf/all.css?v=83c949450c8b"> <div id="language-list"> <h2>Shortest Solution by Language</h2> <table class="language-list"> <thead> <tr><td>Language</td><td>User</td><td>Score</td></tr> </thead> <tbody id="languages"> </tbody> </table> </div> <div id="answer-list"> <h2>Leaderboard</h2> <table class="answer-list"> <thead> <tr><td></td><td>Author</td><td>Language</td><td>Size</td></tr> </thead> <tbody id="answers"> </tbody> </table> </div> <table style="display: none"> <tbody id="answer-template"> <tr><td>{{PLACE}}</td><td>{{NAME}}</td><td>{{LANGUAGE}}</td><td>{{SIZE}}</td><td><a href="{{LINK}}">Link</a></td></tr> </tbody> </table> <table style="display: none"> <tbody id="language-template"> <tr><td>{{LANGUAGE}}</td><td>{{NAME}}</td><td>{{SIZE}}</td><td><a href="{{LINK}}">Link</a></td></tr> </tbody> </table>

Yanıtlar:


8

Pyth, 34 bayt

J]wf}z=Jsmsm++.DdkXLdkGXLkdGhld-Jk

gösteri

Bu özellikle iyi golf oynamayan değil ve çok yavaş. Makul bir sürede 2 değişiklikten sonraki hiçbir şeyi kaldıramaz.


3
Ama işe yarıyor ve önemli olan da bu. : P
Conor O'Brien

10

Matlab, 177 163 bayt

function l=c(a,b);m=nnz(a)+1;n=nnz(b)+1;for i=0:m-1;for j=0:n-1;z=max(i,j);try;z=min([l(i,j+1)+1,l(i+1,j)+1,l(i,j)+(a(i)~=b(j))]);end;l(i+1,j+1)=z;end;end;l=l(m,n)

Bu, bu formülün basit bir uygulamasıdır:

görüntü tanımını buraya girin

Ungolfed:

function l=l(a,b);
m=nnz(a)+1;
n=nnz(b)+1;
for i=0:m-1;
    for j=0:n-1;
        z=max(i,j);
        try;
            z=min([l(i,j+1)+1,l(i+1,j)+1,l(i,j)+(a(i)~=b(j))]);
        end;
        l(i+1,j+1)=z;
    end;
end;
l=l(m,n)

Eğer puan kodu girdiğiniz kod değilse, lütfen puan kodunu ekleyin. Aksi halde dışarı atılabilecek bir sürü boşluk olduğunu düşünüyorum .
Alex A.

1
@AlexA. girinti amaçlı öndeki boşluk ve yeni satırlar sayılmaz (ve güvenle kaldırılabilir). Bir zamanlar unce buna izin verildi ve kimse şikayet etmedi.
edc65

1
@ edc65 Şimdiki meta konsensüs , atılan kodun sağlanması gerektiği yönünde.
Alex A.

2
Öyleyse, çoğunluk okunamayan versiyonu tercih ediyor. Hala okunaklı versiyona izin veriyorum, eğer biri gerçekten neler olup bittiğini görmek isteyebilirse =)
kusur

2
Hem golf gönderimini (puanlanan) hem de asılsız versiyonunu sağlamak yaygın bir uygulamadır, sadece atılanın dahil edilmesini şart koşuyoruz. ;)
Alex A.

7

Python 2, 151 140 138 bayt

Levenshtein mesafesinin Vikipedi temelli yavaş özyinelemeli uygulaması ( 11 karakterin tıraş edilmesi için @Kenney ve başka 2 için @ Sherlock9'a teşekkürler).

def l(s,t):
 def f(m,n):
  if m*n<1:return m or n
  return 1+min([f(m-1,n),f(m,n-1),f(m-1,n-1)-(s[m-1]==t[n-1])])
 return f(len(s),len(t))

Sunulan test durumları için doğru cevapların verilmesi:

assert l("tar", "tarp") == 1
assert l("turing", "tarpit") == 4
assert l("antidisestablishmentarianism", "bulb") == 27        
assert l("atoll", "bowl") == 3

1
Gibi bir şey if !n*m:return n if n else mve başka 2 tarafından yaparak 3-4 bayt kadar tasarruf edebilirsiniz return 1+min([ f(..), f(..), f(..) - (s[..] == t[..]) ]).
Kenney,

Bunun f(m-1,n-1)-(s[m-1]==t[n-1])yerine 2 bayttan tasarruf edersiniz f(m-1,n-1)+(s[m-1]!=t[n-1])-1.
Sherlock9

20 karakter golf
oynadı

5

JavaScript (ES6) 106 113 122

@Neil önerilerini takip ederek kaydedilen 16 baytı düzenle

Anonim bir işlev olarak.

(s,t)=>[...s].map((u,i)=>w=w.map((v,j)=>p=j--?Math.min(p,v,w[j]-(u==t[j]))+1:i+1),w=[...[,...t].keys()])|p

Bu, Wagner-Fischer algoritmasının aynen bağlantılı wikipedia makalesinde açıklandığı gibi, iki matris satırlı yinelemeli bölümde (aslında sadece 1 satır kullanılsa bile - dizi w ) yapılan bir golf uygulamasıdır.

Daha az golf oynadı

(s,t)=>
{
  w = [...[0,...t].keys()];
  for(i = 0; i < s.length; i++)
    w = w.map((v,j)=>
              p = j
              ? Math.min(p+1, v+1, w[j-1] + (s[i]!=t[j-1]))
              : i+1
             );
  return p
}

Test pasajı

L=(s,t)=>[...s].map((u,i)=>w=w.map((v,j)=>p=j--?Math.min(p,v,w[j]-(u==t[j]))+1:i+1),w=[...[,...t].keys()])|p

console.log=x=>O.textContent+=x+'\n';

[["atoll", "bowl"],["tar", "tarp"]
,["turing", "tarpit"],["antidisestablishmentarianism", "bulb"]]
.forEach(t=>console.log(t+' => '+L(...t)))
<pre id=O></pre>


1
Onun [...[0,...t].keys()]yerine kullanabilir misin ? Mümkünse 2 bayt kaydeder.
Neil

1
@Neil çirkin görünüyor ama daha kısa. Thx
edc65

1
Aslında başka bir bayt kurtarabilirsin, [...[,...t].keys()]bence de işe yarıyor.
Neil

Kullanarak başka bir baytı tıraş etmeyi başardım [...s].map():(s,t)=>(w=[...[,...t].keys()],[...s].map((u,i)=>w=w.map((v,j)=>p=j--?Math.min(p,v,w[j]-(s[i-1]==t[j]))+1:i)),p)
Neil

@Neil harika, tekrar teşekkürler!
edc65

4

Python 2, 118 bayt

Bu çözümün bir golfü , ancak Willem bir yıldır açıkmış gibi görünmüyor, bu yüzden kendim göndermem gerekecek:

def l(s,t):f=lambda m,n:m or n if m*n<1else-~min(f(m-1,n),f(m,n-1),f(m-1,n-1)-(s[m-1]==t[n-1]));print f(len(s),len(t))

Repl.it’de dene

İki dizge alır ve uzaklığa STDOUT( meta tarafından izin verilen ) çıktı verir. Lütfen önerileri yorumlayın, bunun daha fazla golf oynayabileceğinden eminim.


Her şeyi bir fonksiyona sarmak gerekli midir? İki input()s kullanabilir misin input().split()?
Sherlock 9

@ Sherlock9 Bunu denedim, ancak söyleyebileceğim kadarıyla 1 byte daha
pahalı

Doğru, ben tanımlamak gerektiğini unuttum sve tkodunda bir yerde. Boşver. İyi iş: D
Sherlock9

Willem'in neden kullanıldığından emin değilim m or n. İle değiştirebilirsiniz m+n.
Arnauld

3

AutoIt , 333 bayt

Func l($0,$1,$_=StringLen,$z=StringMid)
Dim $2=$_($0),$3=$_($1),$4[$2+1][$3+1]
For $5=0 To $2
$4[$5][0]=$5
Next
For $6=0 To $3
$4[0][$6]=$6
Next
For $5=1 To $2
For $6=1 To $3
$9=$z($0,$5,1)<>$z($1,$6,1)
$7=1+$4[$5][$6-1]
$8=$9+$4[$5-1][$6-1]
$m=1+$4[$5-1][$6]
$m=$m>$7?$7:$m
$4[$5][$6]=$m>$8?$8:$m
Next
Next
Return $4[$2][$3]
EndFunc

Örnek test kodu:

ConsoleWrite(l("atoll", "bowl") & @LF)
ConsoleWrite(l("tar", "tarp") & @LF)
ConsoleWrite(l("turing", "tarpit") & @LF)
ConsoleWrite(l("antidisestablishmentarianism", "bulb") & @LF)

verim

3
1
4
27

3

k4, 66 bayt

{$[~#x;#y;~#y;#x;&/.z.s'[-1 0 -1_\:x;0 -1 -1_\:y]+1 1,~(*|x)=*|y]}

Algo bir sıkıcı ve temel olarak ungolfed impl. Ör .:

  f:{$[~#x;#y;~#y;#x;&/.z.s'[-1 0 -1_\:x;0 -1 -1_\:y]+1 1,~(*|x)=*|y]}
  f["kitten";"sitting"]
3
  f["atoll";"bowl"]
3
  f["tar";"tarp"]
1
  f["turing";"tarpit"]
4
  f["antidisestablishmentarianism";"bulb"]
27

3

Cidden, 86 82 78 bayt

,#,#`k;;;░="+l"£@"│d);)[]oq╜Riu)@d);)@[]oq╜Riu(@)@)@[]oq╜Ri3}@)=Y+km"£@IRi`;╗ƒ

Hex Dump:

2c232c23606b3b3b3bb03d222b6c229c4022b364293b295b5d6f71bd526975294064293b29405b
5d6f71bd5269752840294029405b5d6f71bd5269337d40293d592b6b6d229c40495269603bbb9f

Çevrimiçi Deneyin

(Bağlantının farklı bir sürüme ait olduğunu unutmayın; çünkü çevrimiçi tercüman hakkındaki bir şey, indirilebilir tercümanla iyi çalışsa bile, yeni, daha kısa sürümle kopar.)

En basit uygulama hakkında. Özyinelemeli tanımlamaya izin veriyor. Çok yavaştır, çünkü hiçbir not almaz. Belki tabular metodu daha kısa olabilir (belki kayıtları sıralar olarak kullanarak), ancak ne kadar dilin içimdeki eksiklikleri içerdiğine rağmen, bundan çok mutluyum. Bu kullanabilir

[]oq`<code>`Ri

Uygun bir iki argüman işlev çağrısı olarak oldukça hoş bir çağrı oldu.

Açıklama:

,#,#                             Read in two arguments, break them into lists of chars
    `                       `;╗ƒ put the quoted function in reg0 and immediately call it
     k;;;                        put the two lists in a list and make 3 copies
         ░                       replace the latter two with one with empty lists removed
          =                      replace two more with 1 if no empty lists removed, else 0
           "..."£@"..."£@        push the two functions described below, moving 
                                 the boolean above them both
                         I       select the correct function based on the condition
                          Ri     call the function, returning the correct distance
                                 for these substrings

   There are two functions that can be called from the main function above. Each expects 
   two strings, i and j, to be on the stack. This situation is ensured by putting 
   those strings in a list and using R to call the functions with that list as the stack.
   The first is very simple:

+l                             Concatenate the strings and take their length.
                               This is equivalent to the length of the longer
                               string, since one of the strings will be empty.

   The second function is very long and complicated. It will do the "insertion, deletion, 
   substitution" part of the recursive definition. Here's what happens in 4 parts:

│d);)                          After this, the stack is top[i-,j,i,j,ci,i-], where i- is 
                               list i with its last character, ci, chopped off.
     []oq                      this puts i- and j into a list so that they can be passed
                               as arguments recursively into the main function
         ╜Riu                  this calls the main function (from reg0) with the args
                               which will return a number to which we add 1 to get #d,
                               the min distance if we delete a character
)@d);)@                        After this, the stack is top[i,j-,ci,i-,#d,cj,j-], where 
                               j- and cj are the same idea as i- and ci
       []oq╜Riu                listify arguments, recurse and increment to get #i
                               (distance if we insert)
(@)@)@                         After this, the stack is top[i-,j-,#d,cj,#i,ci]
      []oq╜Ri                  listify arguments, recurse to get min distance between 
                               them but we still need to add 1 when we'd need to 
                               substitute because the chars we chopped off are different
(((@)                          After this, the stack is top[cj,ci,#s,#d,#i]
     =Y                        1 if they are not equal, 0 if they are
       +                       add it to the distance we find to get the distance
                               if we substitute here
        k                      put them all in a list
         m                     push the minimum distance over the three options

Kodun ön-öğeden kaçmaya çalıştığını seviyorum :)
mınxomaτ

3

Python 3, 267 216 184 162 bayt

Bu fonksiyon 2 x len(word_2)+1, boyutunda bir dizi kullanarak Levenshtein mesafesini hesaplar .

Düzenleme: Bu Willem'in Python 2 cevabına yaklaşmıyor, ama burada ve burada pek çok küçük iyileştirme ile daha golfçü bir cevap.

def e(p,q):
 m=len(q);r=range;*a,=r(m+1);b=[1]*-~m
 for i in r(len(p)):
  for j in r(m):b[j+1]=1+min(a[j+1],b[j],a[j]-(p[i]==q[j]))
  a,b=b,[i+2]*-~m
 return a[m]

Ungolfed:

def edit_distance(word_1,word_2):
    len_1 = len(word_1)
    len_2 = len(word_2)
    dist = [[x for x in range(len_2+1)], [1 for y in range(len_2+1)]]
    for i in range(len_1):
        for j in range(len_2):
            if word_1[i] == word_2[j]:
                dist[1][j+1] = dist[0][j]
            else:
                deletion = dist[0][j+1]+1
                insertion = dist[1][j]+1
                substitution = dist[0][j]+1
                dist[1][j+1] = min(deletion, insertion, substitution)
        dist[0], dist[1] = dist[1], [i+2 for m in range(len_2+1)]
    return dist[0][len_2]

3

Retina , 78 72 bayt

&`(.)*$(?<!(?=((?<-4>\4)|(?<-1>.(?<-4>)?))*,(?(4),))^.*,((.)|(?<-1>.))*)

Çevrimiçi deneyin!

Bir şekilde, bu sonuç, regex'in eşleştiği pozisyonların sayısı olduğu saf bir regex çözümüdür. Çünkü neden olmasın...

Adil uyarı, bu süper verimsiz. Bunun işe yaraması, mümkün olan en az değişiklikle başlayıp, dizeleri eklemeler, silme ve sübstitüsyonlarla eşleştirmenin mümkün olana kadar bir taneye izin vermesine izin veren, mümkün olan en az değişiklikle başlayarak, mümkün olan en basit düzenlemeleri zorlayan, regex motorunun geri izleyicisine gerçek optimizasyonu boşaltmasıdır. .

Biraz daha mantıklı bir çözüm için bu , eşleştirmeyi yalnızca bir kez yapar ve olumsuz görünümleri yoktur. Burada sonuç, örneğin C # 2ile erişebileceğiniz gruptaki yakalama sayısıdır match.Groups[2].Captures.Count. Yine de korkunç derecede verimsiz.

açıklama

Yukarıdaki ikinci sürümü açıklıyorum, çünkü kavramsal olarak biraz daha kolay (sadece tek bir regex maçı olduğu için). İşte gruplandırılmış bir versiyon, grupları adlandırdım (veya onları yakalamamasına neden oldum) ve yorumlar ekledim. Bir gözbebekindeki bileşenlerin arkadan öne doğru okunması gerektiğini, fakat bunların içindeki alternatiflerin ve gözlerin önden arkaya okunması gerektiğini unutmayın. Evet.

.+                      # Ensures backtracking from smallest to largest for next repetition
(?<ops>(?<distance>.))* # This puts the current attempted distances onto two different stacks,
                        # one to work with, and one for the result.
$                       # Make sure the lookbehind starts from the end.
(?<=                    # The basic idea is now to match up the strings character by character,
                        # allowing insertions/deletions/substitutions at the cost of one capture
                        # on <ops>. Remember to read from the bottom up.
  (?=                   # Start matching forwards again. We need to go through the other string
                        # front-to-back due to the nature of the stack (the last character we
                        # remembered from the second string must be the first character we check
                        # against in the first string).
    (?:
      (?<-str>\k<str>)  # Either match the current character against the corresponding one from
                        # the other string.
    |
      (?<-ops>          # Or consume one operation to...
        .               # consume a character without matching it to the other string (a deletion)
        (?<-str>)?      # optionally dropping a character from the other string as well 
                        # (a substitution).
      )
    )*                  # Rinse and repeat.
    ,(?(str),)          # Ensure we reached the end of the first string while consuming all of the 
                        # second string. This is only possible if the two strings can be matched up 
                        # in no more than <distance> operations.
  )
  ^.*,                  # Match the rest of string to get back to the front.
  (?:                   # This remembers the second string from back-to-front.
    (?<str>.)           # Either capture the current character.
  |
    (?<-ops>.)          # Or skip it, consuming an operation. This is an insertion.
  )*
)

72 baytlık sürümüne tek fark, bizim lider damla olmasıdır .+biz sonunda pozisyonları bularak (başlangıçta ve ikinci grup) yok yeterli <ops>ve bu pozisyonların her sayar.


3

Haskell , 67 64 bayt

e@(a:r)#f@(b:s)=sum[1|a/=b]+minimum[r#f,e#s,r#s]
x#y=length$x++y

Çevrimiçi deneyin! Örnek kullanım: "turing" # "tarpit"verim 4.


Açıklama (önceki 67 byte versiyonu için)

e@(a:r)#f@(b:s)|a==b=r#s|1<3=1+minimum[r#f,e#s,r#s]
x#y=length$x++y

Bu özyinelemeli bir çözümdür. İki dizeleri göz önüne alındığında eve f, öncelikle ilk karakterlerini karşılaştırmak ave b. Bunlar eşit ise, o zaman Levenshtein mesafesi eve fLevenshtein mesafe ile aynıdır rve s, geri kalan eve filk karakter alınmasından sonra çekilmesi. Aksi takdirde, ikisinden biri aveya bkaldırılması gerekir veya biri biri ile ikame edilir. [r#f,e#s,r#s]Levenshtein'i tekrar tekrar bu üç vaka için hesaplar, minimumen küçüğünü alır 1ve gerekli çıkarma veya değiştirme işlemini hesaba katmak için eklenir.

Dizelerden biri boşsa, biz ve ikinci satırda yukarı çıkarız. Bu durumda, mesafe yalnızca boş olmayan dizenin uzunluğu veya eşdeğerde bir araya getirilmiş her iki dizinin uzunluğu.


1
Vay canına, bu gerçekten zarif ve kısa, cidden iyi bir çözüm.
ggPeti

3

Python 3 , 105 94 93 bayt

Xnor'dan -11 bayt

l=lambda a,b:b>""<a and min(l(a[1:],b[1:])+(a[0]!=b[0]),l(a[1:],b)+1,l(a,b[1:])+1)or len(a+b)

Vikikitap'taki en kısa uygulamanın Golf sürümü .

Çevrimiçi deneyin!


Güzel çözüm. l=İhtiyaçlar dahil ve işlev özyinelemeli çünkü sayılacak. Baz kasaları birleştirebilirsiniz if b>""<a else len(a+b).
xnor

Operatörler ile iyi oyun, teşekkürler!
movatica

2

Haskell, 136 bayt

Çağrı e. Biraz yavaş antidisestablishmentarianismvs.

l=length
e a b=v a(l a)b(l b)
v a i b j|i*j==0=i+j|0<1=minimum[1+v a(i-1)b j,1+v a i b(j-1),fromEnum(a!!(i-1)/=b!!(j-1))+v a(i-1)b(j-1)]

2

Jolf, 4 bayt

Burada dene!

~LiI
~L   calculate the Levenshtein distance of
  i   input string
   I  and another input string

Bu eklentiyi dün ekledim, ancak bu zorluğu bugün gördüm, yani şimdi. Yine de, bu cevap rekabetçi değil.

Daha yeni bir sürümde:

~Li

örtük ikinci girişi alır.


" Kodunuz bir program veya işlev olmalıdır. Adlandırılmış bir işlev olması gerekmez, ancak Levenshtein mesafesini doğrudan hesaplayan yerleşik bir işlev olamaz . Diğer yerleşik yapılara izin verilir. "
Kevin Cruijssen

Ah, rekabet etmediğini söylediğini görmedin .. Başlığa koymak daha iyi, ya da yerleşik olmadan geçerli bir program / işlev eklemek.
Kevin Cruijssen

2

GNU Prolog, 133 bayt

m([H|A],B):-B=A;B=[H|A].
d([H|A]-[H|B],D):-d(A-B,D).
d(A-B,D):-A=B,D=0;D#=E+1,m(A,X),m(B,Y),d(X-Y,E).
l(W,D):-d(W,D),(E#<D,l(W,E);!).

Argüman olarak bir tuple alır. Kullanım örneği:

| ?- l("turing"-"tarpit",D).

D = 4

yes

mbelirtir Bolduğu Adoğrudan ya ilk karakteri ile kaldırıldı. dBağlantı elemanları arasındaki düzenleme mesafesini mhesaplamak için alt rutin olarak kullanılır (yani, birini diğerine dönüştüren bir dizi düzenlemenin mesafesi). O zaman l, minimum olanı bulmak için standart bir püf noktasıdır d(keyfi bir mesafe alırsınız, daha sonra keyfi daha küçük bir mesafe alırsınız, daha küçük kalana kadar tekrarlayın).


1

Perl, 168 166 163 bayt

sub l{my($S,$T,$m)=(@_,100);$S*$T?do{$m=++$_<$m?$_:$m for l($S-1,$T),l($S,--$T),l(--$S,$T)-($a[$S]eq$b[$T]);$m}:$S||$T}print l~~(@a=shift=~/./g),~~(@b=shift=~/./g)

Özyinelemeli uygulama. A'ya kaydedin file.plve olarak çalıştırın perl file.pl atoll bowl.

sub l {
    my($S,$T,$m)=(@_,100);

    $S*$T
    ? do {
        $m = ++$_ < $m ? $_ : $m
        for
            l($S-1,   $T),
            l($S  , --$T),
            l(--$S,   $T) - ($a[$S] eq $b[$T])
        ;    
        $m
    }
    : $S||$T
}
print l~~(@a=shift=~/./g),~~(@b=shift=~/./g)


Diğer iki uygulama daha uzundur (tam matris: 237 bayt, iki tek satır yinelemeli: 187).

  • 166 güncellemesi : ()aramayı atlayın l.
  • güncelleme 163 : trinerde returnkötüye kullanarak ortadan dokaldır.


0

C, 192 bayt

#define m(x,y) (x>y?x:y)
#define r(x,y) l(s,ls-x,t,lt-y)
int l(char*s,int ls,char*t,int lt){if(!ls)return lt;if(!lt)return ls;a=r(1,1);if(s[ls]==t[ls])return a;return m(m(r(0,1),r(1,0)),a)+1;}
---------

Detaylı

#include <stdio.h>

#define m(x,y) (x>y?x:y)
#define f(x) char x[128];fgets(x,100,stdin)
#define r(x,y) l(s,ls-x,t,lt-y)

int l(char*s,int ls,char*t,int lt)
{
    if(!ls) return lt;
    if(!lt) return ls;

    int a = r(1,1);
    if(s[ls]==t[ls]) return a;

    return m(m(r(0,1),r(1,0)),a)+1;
}

int main(void)
{
    f(a);
    f(b);
    printf("%d", l(a,strlen(a),b,strlen(b)));
    return 0;
}

0

C #, 215 210 198

public int L(string s,string t){int c,f,a,i,j;var v=new int[100];for(c=i=0;i<s.Length;i++)for(f=c=i,j=0;j<t.Length;j++){a=c;c=f;f=i==0?j+1:v[j];if(f<a)a=f;v[j]=c=s[i]==t[j]?c:1+(c<a?c:a);}return c;}

daha okunaklı:

public int L(string s,string t){
    int c,f,a,i,j;
    var v=new int[100];
    for(c=i=0;i<s.Length;i++)
        for(f=c=i,j=0;j<t.Length;j++){
            a=c;
            c=f;
            f=(i==0)?j+1:v[j];
            if (f<a) a=f;
            v[j]=c=(s[i]==t[j])?c:1+((c<a)?c:a);
        }
    return c;
}

0

PowerShell v3 +, 247 Bayt

$c,$d=$args;$e,$f=$c,$d|% le*;$m=[object[,]]::new($f+1,$e+1);0..$e|%{$m[0,$_]=$_};0..$f|%{$m[$_,0]=$_};1..$e|%{$i=$_;1..$f|%{$m[$_,$i]=(($m[($_-1),$i]+1),($m[$_,($i-1)]+1),($m[($_-1),($i-1)]+((1,0)[($c[($i-1)]-eq$d[($_-1)])]))|sort)[0]}};$m[$f,$e]

LD'lerin de dahil olduğu başka zorlukları çözmek için bunu bitirdim.

Yorumlarla kod açıklaması.

# Get both of the string passed as arguments. $c being the compare string
# and $d being the difference string. 
$c,$d=$args

# Save the lengths of these strings. $e is the length of $c and $f is the length of $d
$e,$f=$c,$d|% le*

# Create the multidimentional array $m for recording LD calculations
$m=[object[,]]::new($f+1,$e+1)

# Populate the first column 
0..$e|%{$m[0,$_]=$_}

# Populate the first row
0..$f|%{$m[$_,0]=$_}

# Calculate the Levenshtein distance by working through each position in the matrix. 
# Working the columns
1..$e|%{
    # Save the column index for use in the next pipeline
    $i=$_

    # Working the rows.
    1..$f|%{
        # Calculate the smallest value between the following values in the matrix relative to this one
        # cell above, cell to the left, cell in the upper left. 
        # Upper left also contain the cost calculation for this pass.    
        $m[$_,$i]=(($m[($_-1),$i]+1),($m[$_,($i-1)]+1),($m[($_-1),($i-1)]+((1,0)[($c[($i-1)]-eq$d[($_-1)])]))|sort)[0]
    }
}
# Return the last element of the matrix to get LD 
$m[$f,$e]

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.