Cada paso de la distancia de Levenshtein

18

En este desafío, escribirá un programa que toma dos cadenas separadas por una nueva línea, s1 (la primera línea) y s2 (la segunda línea), como entrada (STDIN o la más cercana). Puede suponer que la longitud de s1 siempre será menor que 30 y mayor que la longitud de s2. El programa debería generar cada paso en la distancia levenshtein de s1 a s2.

Para aclarar lo que significa cada paso en la distancia levenshtein, el programa imprimirá n cadenas, donde n es la distancia levenshtein entre s1 y s2, y la distancia levenshtein entre dos cadenas adyacentes siempre será una. El orden no importa. La salida debe estar separada por una nueva línea y no incluir s1, solo los intermedios y s2. El programa también debería ejecutarse en menos de un minuto en una computadora moderna.

Ejemplos:

Entrada:

Programming
Codegolf

Salida:

rogramming
Cogramming
Coramming
Coamming
Codmming
Codeming
Codeging
Codegong
Codegolg
Codegolf

Entrada:

Questions
Answers

Salida:

uestions
Aestions
Anstions
Ansions
Answons
Answens
Answers

Entrada:

Offline
Online

Salida:

Ofline
Online

Entrada:

Saturday
Sunday

Salida:

Sturday
Surday
Sunday

Aquí hay un enlace a un script de Python que imprime la distancia y los pasos.

Reglas adicionales:

Este es el código de golf, así que mantén tu código corto; el código más corto gana!

Loovjo
fuente
1
Para mi edición, supuse que la entrada sería de la forma s1(newline)s2, sin embargo, después de haber revisado la pregunta nuevamente, me pregunto si, en cambio, pretendía que el programa seleccionara s1 y s2 en función de la longitud de 2 cadenas ingresadas. en cualquier orden, ¿le importaría aclarar este punto? Es decir, ¿suponemos que la entrada es s1 seguida de s2, o seleccionamos s1 y s2 en función de la longitud de las dos entradas?
VisualMelon
¿Tiene que ejecutarse una respuesta en un tiempo razonable?
KSab
Camper - Amperio, distancia 2, el script de Python se ejecuta para siempre ...
edc65
¿Cuán estricto es "recibir información de STDIN o más cercano"? ¿Puedo escribir una función que tome la entrada a través del argumento de función? La respuesta actualmente aceptada lo hace.
nimi

Respuestas:

4

Javascript, 167 161 154 bytes

function l(a,b,d){if(a!=b){if(a[l="length"]>b[l])a=a[s="slice"](1),d=-1;else if(a[d]!=b[d])a=a[s](0,d)+b[d]+a[s](d+1);document.write(a+"<p>");l(a,b,++d)}}

Llamar con l("Programming","golf")

Codepen

Código desgolfado (y anotado) (desactualizado pero se entiende):

function l(a, b, d) {
  s = "substring"; //saving this to a string lets us call it with a[s] later
  if (a != b) { //if the strings aren't the same, continue
    if (a.length > b.length) { //if a is still greater than b we can delete characters
      a = a[s](1); //delete the first character from a
      d = -1 //when we start swapping characters, we'll need d to start at 0
    } else if (a[d] != b[d]) { //if the d'th character isn't the same, we can swap them
      a = a[s](0, d) + b[d] + a[s](d + 1) //swap the d'th character of b into a
    }
    document.write(a + "<p>"); //the first call to document.write overwrites the page but successive calls append the output 
    l(a, b, ++d) //increment d and recurse
  }
}
9999 años
fuente
función l (a, b, d) {s = "slice"; if (a! = b) {if (a.length> b.length) a = a [s] (1), d = -1; else if (a [d]! = b [d]) a = a [s] (0, d) + b [d] + a [s] (d + 1); document.write (a + "<p>" ); l (a, b, ++ d)}}
Dr. Pain
@nimi: Si lo llamas con dos argumentos (por ejemplo, l ("programación", "codegolf") funciona igual, así que supongo que tu punto es nulo.
9999 años
Además, declarar sdentro a=a[s](1)como a=a[s="slice"](1)guarda algunos bytes.
Mama Fun Roll
1
Según el enlace a codepen, su programa genera 11 pasos para "Programming"-> "Codegolf", pero debería ser 10.
nimi
10

Haskell, 201 194 bytes

l=length
g[]n u=map(\_->"")n
g(b:c)[]u=(u++c):g c[]u
g(b:c)n@(o:p)u|b==o=g c p(u++[o])|1<2=((u++o:c):g c p(u++[o]))!((u++c):g c n u)
a!b|l a<l b=a|1<2=b
p[a,n]=g a n""
f=interact$unlines.p.lines

Más de lo esperado. Tal vez pueda jugar golf un poco ...

Ejemplo de uso:

*Main> f                     -- call via f
Questions                    -- User input
Answers                      -- no newline after second line!
uestions                     -- Output starts here
Aestions
Anstions
Ansions
Answons
Answens
Answers

Es una fuerza bruta que decide entre cambiar y eliminar si los caracteres iniciales difieren.

nimi
fuente
¿Cuánto tiempo lleva correr?
Loovjo
¿Cómo puedo probar (quizás ideone)?
edc65
@Loovjo: las cadenas más cortas, como sus ejemplos, se calculan instantáneamente, el peor de los casos es aproximadamente 1: 30min. He interpretado que el "debería" en "debería ejecutarse en menos de un minuto", no como un límite estricto (debería vs. debe). Si esto es imprescindible, puedo agregar un "paquete de rendimiento" de unos 20 bytes.
nimi
@ edc65: sí, ideone, pero espera que la función que se ejecute se llame "main". Prueba: ideone.com/CUgU8W
nimi