Si bien hay muchas preguntas de distancia de edición, como esta , no hay una pregunta simple para escribir un programa que calcule la distancia de Levenshtein.
Alguna exposición
La distancia de edición de Levenshtein entre dos cadenas es el número mínimo posible de inserciones, eliminaciones o sustituciones para convertir una palabra en otra. En este caso, cada inserción, eliminación y sustitución tiene un costo de 1.
Por ejemplo, la distancia entre roll
y rolling
es 3, porque las eliminaciones cuestan 1, y necesitamos eliminar 3 caracteres. La distancia entre toll
y tall
es 1, porque las sustituciones cuestan 1.
Reglas
- La entrada será de dos cadenas. Puede suponer que las cadenas son minúsculas, solo contienen letras, no están vacías y tienen un máximo de 100 caracteres de longitud.
- La salida será la distancia mínima de edición de Levenshtein de las dos cadenas, como se definió anteriormente.
- Su código debe ser un programa o una función. No necesita ser una función con nombre, pero no puede ser una función integrada que calcule directamente la distancia de Levenshtein. Se permiten otros complementos.
- Este es el código de golf, por lo que gana la respuesta más corta.
Algunos ejemplos
>>> lev("atoll", "bowl")
3
>>> lev("tar", "tarp")
1
>>> lev("turing", "tarpit")
4
>>> lev("antidisestablishmentarianism", "bulb")
27
Como siempre, si el problema no está claro, hágamelo saber. ¡Buena suerte y buen golf!
Catalogar
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 bytesEsta es una implementación sencilla de esta fórmula:
Sin golf:
fuente
Python 2,
151140138 bytesImplementación lenta y recursiva de la distancia de Levenshtein basada en Wikipedia (Gracias a @Kenney por el afeitado de 11 caracteres y @ Sherlock9 por otros 2).
Dando las respuestas correctas para los casos de prueba presentados:
fuente
if !n*m:return n if n else m
, y otro 2 porreturn 1+min([ f(..), f(..), f(..) - (s[..] == t[..]) ])
.f(m-1,n-1)-(s[m-1]==t[n-1])
lugar def(m-1,n-1)+(s[m-1]!=t[n-1])-1
.JavaScript (ES6) 106
113 122Edite 16 bytes guardados siguiendo las sugerencias de @Neil
Como una función anónima.
Esta es una implementación de golf del algoritmo Wagner-Fischer exactamente como se describe en el artículo de Wikipedia vinculado, en la sección Iterativo con dos filas de matriz (incluso si de hecho, solo se usa 1 fila - matriz w )
Menos golf
Fragmento de prueba
fuente
[...[0,...t].keys()]
en su lugar? Ahorra 2 bytes si puedes.[...[,...t].keys()]
también funciona, creo.[...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 bytes
Un campo de golf de esta solución , pero no parece que Willem haya estado funcionando durante un año, así que tendré que publicarlo yo mismo:
Probar repl.it
Toma dos cadenas y genera la distancia a
STDOUT
( permitido por meta ). Por favor comente sugerencias, estoy seguro de que esto se puede jugar más.fuente
input()
so aninput().split()
?s
yt
en algún lugar del código. No importa. Buen trabajo: Dm or n
. Puedes reemplazarlo conm+n
.AutoIt , 333 bytes
Código de prueba de muestra:
rendimientos
fuente
k4, 66 bytes
Una implicación aburrida y básicamente no golfista del algo. Ex.:
fuente
En serio,
868278 bytesHex Dump:
Pruébalo en línea
(Tenga en cuenta que el enlace es a una versión diferente porque algo sobre el intérprete en línea rompe con la nueva versión más corta, aunque funciona bien con el intérprete descargable).
Se trata de la implementación más sencilla. En serio, permite la definición recursiva. Es muy lento porque no memoriza nada. Tal vez el método tabular podría ser más corto (tal vez usando los registros como filas), pero estoy bastante contento con esto, a pesar de las deficiencias de kludging-my-way-around-the-language que contiene. Que uno puede usar
como una llamada a la función de dos argumentos fue un buen hallazgo.
Explicación:
fuente
Python 3,
267216184162 bytesEsta función calcula la distancia de Levenshtein usando una matriz
2 x len(word_2)+1
de tamaño.Editar: Esto no se acerca a la respuesta de Willem's Python 2, pero aquí hay una respuesta más precisa con muchos pequeños detalles aquí y allá.
Sin golf:
fuente
Retina ,
7872 bytesPruébalo en línea!
En cierto modo, esta es una solución pura de expresiones regulares donde el resultado es el número de posiciones desde las cuales coincide la expresión regular. Porque, porque no...
Advertencia justa, esto es super ineficiente. La forma en que esto funciona es que descarga la optimización real al backtracker del motor regex, que simplemente fuerza bruta todas las alineaciones posibles, comenzando con la menor cantidad de alteraciones posible y permitiendo una más hasta que sea posible combinar las cadenas con adiciones, eliminaciones y sustituciones .
Para una solución un poco más sensata, esta hace la correspondencia solo una vez y no tiene ningún aspecto negativo. Aquí, el resultado es el número de capturas en grupo
2
, a las que puede accedermatch.Groups[2].Captures.Count
en C #, por ejemplo. Sin embargo, todavía es terriblemente ineficiente.Explicación
Estoy explicando la segunda versión anterior, porque conceptualmente es un poco más fácil (ya que es solo una coincidencia de expresiones regulares). Aquí hay una versión sin golf que he nombrado los grupos (o los hice no capturadores) y agregué comentarios. Recuerde que los componentes en una vista posterior deben leerse de atrás hacia adelante, pero las alternativas y las miradas dentro de ellas deben leerse de adelante hacia atrás. Sí.
La única diferencia con la versión de 72 bytes es que podemos eliminar el líder
.+
(y el segundo grupo al principio) al encontrar posiciones al final donde no tenemos suficiente<ops>
y contar todas esas posiciones.fuente
Haskell ,
6764 bytesPruébalo en línea! Ejemplo de uso:
"turing" # "tarpit"
rendimientos4
.Explicación (para la versión anterior de 67 bytes)
Esta es una solución recursiva. Dadas dos cadenas
e
yf
, primero comparamos sus primeros personajesa
yb
. Si son iguales, entonces la distancia de Levenshtein dee
yf
es la misma que la distancia de Levenshtein der
ys
, el resto dee
yf
después de eliminar los primeros caracteres. De lo contrario,a
ob
necesita ser eliminado, o uno es sustituido por el otro.[r#f,e#s,r#s]
calcula recursivamente el Levenshtein para esos tres casos,minimum
elige el más pequeño y1
se agrega para tener en cuenta la operación necesaria de eliminación o reemplazo.Si una de las cadenas está vacía, nosotros y arriba en la segunda línea. En este caso, la distancia es solo la longitud de la cadena no vacía, o equivalentemente la longitud de ambas cadenas concatenadas juntas.
fuente
Python 3 ,
1059493 bytes-11 bytes por xnor
Versión de golf de la implementación más corta en Wikilibros .
Pruébalo en línea!
fuente
l=
necesidades que deben incluirse y se contaron porque la función es recursivo. Puede combinar los casos base enif b>""<a else len(a+b)
.Haskell, 136 bytes
Llamada
e
. Poco lento,antidisestablishmentarianism
etc.fuente
Jolf, 4 bytes
Pruébalo aquí!
Agregué esa construcción ayer, pero vi este desafío hoy, es decir, justo ahora. Aún así, esta respuesta no es competitiva.
En una versión más nueva:
toma una segunda entrada implícita.
fuente
GNU Prolog, 133 bytes
Toma una tupla como argumento. Ejemplo de uso:
m
especifica queB
esA
directamente o con su primer carácter eliminado.d
se usam
como subrutina para calcular una distancia de edición entre los elementos de tupla (es decir, la distancia de una serie de ediciones que convierte una en la otra). Entoncesl
es un truco estándar para encontrar el mínimo ded
(toma una distancia arbitraria, luego toma una distancia arbitraria más pequeña, repite hasta que no puedas hacerlo más pequeño).fuente
Perl,
168166163 bytesImplementación recursiva. Guardar en
file.pl
y correr comoperl file.pl atoll bowl
.Las otras dos implementaciones son más largas (matriz completa: 237 bytes,
dositerativas de una fila: 187).()
al llamarl
.return
mediante el abusodo
en trinario.fuente
APL (Dyalog Classic) , 34 bytes
Pruébalo en línea!
fuente
C, 192 bytes
Detallado
fuente
C #,
215210198más legible:
fuente
PowerShell v3 +, 247 bytes
Terminé haciendo esto para resolver otros desafíos relacionados con los LD.
Explicación del código con comentarios.
fuente
JavaScript (ES6),
95 9189 bytesToma entrada como
(source)(target)
. Esencialmente un puerto de la respuesta Python de @Willem (luego optimizado por @FlipTack ).Pruébalo en línea!
fuente