Bien qu'il existe de nombreuses questions de distance d'édition, comme celle-ci , il n'y a pas de question simple pour écrire un programme calculant la distance de Levenshtein.
Une Exposition
La distance de levée Levenshtein entre deux chaînes est le nombre minimal possible d'insertions, de suppressions ou de substitutions pour convertir un mot en un autre. Dans ce cas, chaque insertion, suppression et substitution a un coût de 1.
Par exemple, la distance entre roll
et rolling
est égale à 3, car les suppressions coûtent 1 et nous devons supprimer 3 caractères. La distance entre toll
et tall
est égale à 1, car les substitutions coûtent 1.
Règles
- L'entrée sera deux chaînes. Vous pouvez supposer que les chaînes sont en minuscules, ne contiennent que des lettres, ne sont pas vides et ont une longueur maximale de 100 caractères.
- La sortie correspondra à la distance minimale d’édition de Levenshtein des deux chaînes, comme défini ci-dessus.
- Votre code doit être un programme ou une fonction. Il ne doit pas nécessairement s'agir d'une fonction nommée, mais il ne peut s'agir d'une fonction intégrée qui calcule directement la distance de Levenshtein. Les autres fonctions intégrées sont autorisées.
- C'est le code de golf, donc la réponse la plus courte gagne.
Quelques exemples
>>> lev("atoll", "bowl")
3
>>> lev("tar", "tarp")
1
>>> lev("turing", "tarpit")
4
>>> lev("antidisestablishmentarianism", "bulb")
27
Comme toujours, si le problème n'est pas clair, merci de me le faire savoir. Bonne chance et bon golf!
Catalogue
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>
Matlab,
177163 octetsCeci est une implémentation simple de cette formule:
Ungolfed:
la source
Python 2,
151140138 octetsMise en œuvre lente et récursive de la distance de Levenshtein basée sur Wikipedia (Merci à @Kenney pour le rasage de 11 caractères et à @ Sherlock9 pour un autre 2).
Donner les bonnes réponses pour les cas de test présentés:
la source
if !n*m:return n if n else m
, et 2 autres parreturn 1+min([ f(..), f(..), f(..) - (s[..] == t[..]) ])
.f(m-1,n-1)-(s[m-1]==t[n-1])
place def(m-1,n-1)+(s[m-1]!=t[n-1])-1
.JavaScript (ES6) 106
113 122Editez 16 octets sauvegardés suite aux suggestions de @Neil
En tant que fonction anonyme.
Il s’agit d’une implémentation de l’algorithme de Wagner-Fischer dans le golfe, exactement comme décrit dans l’article lié à Wikipédia, dans la section Itérative avec deux lignes de matrice (même si en fait, une seule ligne est utilisée - tableau w ).
Moins golfé
Extrait de test
la source
[...[0,...t].keys()]
place? Enregistre 2 octets si vous le pouvez.[...[,...t].keys()]
fonctionne aussi, je pense.[...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)
Python 2, 118 octets
Un exemple de cette solution , mais il ne semble pas que Willem soit sur le marché depuis un an, je vais donc devoir le publier moi-même:
Essayez repl.it
Prend deux chaînes et renvoie la distance à
STDOUT
( autorisée par meta ). S'il vous plaît commenter les suggestions, je suis sûr que cela peut être joué plus loin.la source
input()
s ou uninput().split()
?s
ett
quelque part dans le code. Ça ne fait rien. Bon travail: Dm or n
. Vous pouvez le remplacer parm+n
.AutoIt , 333 octets
Exemple de code de test:
les rendements
la source
k4, 66 octets
Un impl ennuyeux et fondamentalement non-golfé de l'algo. Ex.:
la source
Sérieusement,
868278 octetsDécharge Hex:
Essayez-le en ligne
(Notez que le lien est dirigé vers une version différente car quelque chose à propos de l'interprète en ligne rompt avec la nouvelle version plus courte, même si cela fonctionne correctement avec l'interprète téléchargeable.)
Il s’agit de l’implémentation la plus simple qui permet Sérieusement de prendre en compte la définition récursive. C'est très lent parce que ça ne mémoise pas du tout. Peut-être que la méthode tabulaire pourrait être plus courte (peut-être en utilisant les registres comme des lignes), mais je suis assez contente de cela, malgré les faiblesses qu'elle contient. Celui-là peut utiliser
comme un appel de fonction à deux arguments convenable était une bonne trouvaille.
Explication:
la source
Python 3,
267216184162 octetsCette fonction calcule la distance de Levenshtein en utilisant un tableau
2 x len(word_2)+1
de taille.Edit: Cela ne se rapproche pas de la réponse de Willem's Python 2, mais voici une réponse plus détaillée avec beaucoup de petites améliorations ici et là.
Ungolfed:
la source
Rétine ,
7872 octetsEssayez-le en ligne!
En un sens, il s’agit d’une solution purement rationnelle dont le résultat est le nombre de positions à partir desquelles la regex correspond. Parce que pourquoi pas ...
Avertissement juste, c'est super inefficace. La façon dont cela fonctionne consiste à décharger l'optimisation réelle du backtracker du moteur des expressions rationnelles, ce qui force simplement tous les alignements possibles, en commençant par le moins de modifications possibles et en permettant un changement supplémentaire jusqu'à ce qu'il soit possible de faire correspondre les chaînes avec des ajouts, des suppressions et des substitutions. .
Pour une solution légèrement plus judicieuse, celle-ci ne fait l’appariement qu’une seule fois et n’a pas d’apparence négative. Ici, le résultat est le nombre de captures en groupe
2
auquel vous pouvez accédermatch.Groups[2].Captures.Count
en C #, par exemple. C'est quand même horriblement inefficace.Explication
J'explique la deuxième version ci-dessus, parce que c'est conceptuellement un peu plus facile (étant donné qu'il ne s'agit que d'un seul match regex). Voici une version non golfée que j'ai nommée (ou que je n'ai pas capturée) et que j'ai ajoutée des commentaires. N'oubliez pas que les composants d'un regard arrière doivent être lus de l'arrière vers l'avant, mais que les alternatives et les points d'anticipation à l'intérieur de ceux-ci doivent être lus d'avant en arrière. Ouais.
La seule différence par rapport à la version à 72 octets est que nous pouvons laisser tomber le groupe de tête
.+
(et le deuxième groupe au début) en trouvant des positions à la fin où nous n’en avons pas assez<ops>
et compter toutes ces positions.la source
Haskell ,
6764 octetsEssayez-le en ligne! Exemple d'utilisation:
"turing" # "tarpit"
rendements4
.Explication (pour la version précédente de 67 octets)
C'est une solution récursive. Étant donné deux chaînes
e
etf
, nous comparons d’abord leurs premiers caractèresa
etb
. S'ils sont égaux, la distance de Levenshtein dee
etf
est identique à la distance de Levenshtein der
ets
, le reste dee
etf
après la suppression des premiers caractères. Autrement, l'una
ou l' autreb
doit être supprimé, ou l'un est remplacé par l'autre.[r#f,e#s,r#s]
calcule récursivement le Levenshtein pour ces trois cas,minimum
sélectionne le plus petit et1
est ajouté pour prendre en compte l'opération de suppression ou de remplacement nécessaire.Si l'une des chaînes est vide, nous remontons à la deuxième ligne. Dans ce cas, la distance est simplement la longueur de la chaîne non vide ou, de manière équivalente, la longueur des deux chaînes concaténées ensemble.
la source
Python 3 ,
1059493 octets-11 octets par xnor
Version golfée de la plus courte implémentation sur Wikibooks .
Essayez-le en ligne!
la source
l=
doit être inclus et compté car la fonction est récursive. Vous pouvez combiner les cas de base enif b>""<a else len(a+b)
.Haskell, 136 octets
Appel
e
. Peu lent surantidisestablishmentarianism
etc.la source
Jolf, 4 octets
Essayez-le ici!
J'ai ajouté cela hier, mais j'ai vu le défi aujourd'hui, c'est-à-dire tout à l'heure. Pourtant, cette réponse est non compétitive.
Dans une version plus récente:
prend une deuxième entrée implicite.
la source
GNU Prolog, 133 octets
Prend un tuple en argument. Exemple d'utilisation:
m
spécifie qu'ilB
estA
directement ou avec son premier caractère supprimé.d
utilisem
comme sous-routine pour calculer une distance de montage entre les tuple (c’est-à-dire la distance d’une série de modifications qui convertit l’un en l’autre). Ill
s’agit alors d’une astuce classique pour trouver le minimum ded
(vous prenez une distance arbitraire, puis une distance arbitraire plus petite, répétez jusqu’à ce que vous ne puissiez plus réduire).la source
Perl,
168166163 octetsImplantation récursive. Enregistrer dans un
file.pl
et exécuter en tant queperl file.pl atoll bowl
.Les deux autres implémentations sont toutes deux plus longues (matrice complète: 237 octets,
deuxitératives sur une ligne: 187).()
en appelantl
.return
en abusantdo
en trinary.la source
APL (Dyalog Classic) , 34 octets
Essayez-le en ligne!
la source
C, 192 octets
Détaillé
la source
C #,
215210198plus lisible:
la source
PowerShell v3 +, 247 octets
J'ai fini par faire ceci pour résoudre un autre défi impliquant les LD.
Explication de code avec commentaires.
la source
JavaScript (ES6),
95 9189 octetsPrend les entrées en tant que
(source)(target)
. Essentiellement un portage de la réponse Python @ Willem ( optimisé par la suite par @ FlipTack ).Essayez-le en ligne!
la source