La distancia de edición (o Levenshtein) entre dos cadenas es el número mínimo de inserciones, eliminaciones y sustituciones de un solo carácter necesarias para transformar una cadena en la otra. Si las dos cadenas tienen una longitud n cada una, es bien sabido que esto puede hacerse en tiempo O (n ^ 2) mediante programación dinámica. El siguiente código de Python realiza este cálculo para dos cadenas s1
y s2
.
def edit_distance(s1, s2):
l1 = len(s1)
l2 = len(s2)
matrix = [range(l1 + 1)] * (l2 + 1)
for zz in range(l2 + 1):
matrix[zz] = range(zz,zz + l1 + 1)
for zz in range(0,l2):
for sz in range(0,l1):
if s1[sz] == s2[zz]:
matrix[zz+1][sz+1] = min(matrix[zz+1][sz] + 1, matrix[zz][sz+1] + 1, matrix[zz][sz])
else:
matrix[zz+1][sz+1] = min(matrix[zz+1][sz] + 1, matrix[zz][sz+1] + 1, matrix[zz][sz] + 1)
return matrix[l2][l1]
En esta tarea, debe acercarse lo más posible a la distancia de edición pero con una restricción de memoria severa. Su código puede definir una matriz que contiene 1000 enteros de 32 bits y este será el único almacenamiento temporal que use en su cálculo. Todas las variables y estructuras de datos deben estar contenidas en esta matriz. En particular, no podrá implementar el algoritmo anterior en cuanto a las cadenas de longitud 1000, ya que requeriría que almacene al menos 1,000,000 de números. Cuando su idioma no tiene enteros de 32 bits (por ejemplo, Python), simplemente debe asegurarse de no almacenar nunca un número mayor que 2 ^ 32-1 en la matriz.
Puede leer los datos utilizando cualquier biblioteca estándar de su elección sin preocuparse por las restricciones de memoria en esa parte. Para que la competencia sea justa para la parte principal de su código, solo puede usar operaciones que sean funcionalmente equivalentes a las del lenguaje de programación C y no puede usar ninguna biblioteca externa.
Para ser más claro, la memoria para almacenar los datos de entrada o la utilizada por el intérprete de su idioma, JVM, etc. no cuenta para su límite y no puede escribir nada en el disco. Debe asumir que los datos de entrada son de solo lectura cuando están en la memoria, por lo que no puede reutilizarlos para ganar más espacio de trabajo.
¿Qué tengo que implementar?
Su código debe leer en un archivo en el siguiente formato. Tendrá tres líneas. La primera línea es la verdadera distancia de edición. El segundo es la cadena 1 y el tercero es la cadena 2. Lo probaré con los datos de muestra en https://bpaste.net/show/6905001d52e8 donde las cadenas tienen una longitud de 10,000 pero no deberían estar especializadas para estos datos. Debería generar la distancia de edición más pequeña que pueda encontrar entre las dos cadenas.
También deberá probar que su distancia de edición en realidad proviene de un conjunto válido de ediciones. Su código debe tener un interruptor que lo convierta en un modo que pueda usar más memoria (tanto como desee) y genere las operaciones de edición que le dan su distancia de edición.
Puntuación
Tu puntaje será el (optimal edit distance/divided by the edit distance you find) * 100
. Para comenzar, tenga en cuenta que puede obtener una puntuación simplemente contando el número de desajustes entre las dos cadenas.
Puede usar cualquier idioma que desee que esté disponible gratuitamente y sea fácil de instalar en Linux.
Desempate
En el caso de un desempate, ejecutaré su código en mi máquina Linux y el código más rápido gana.
{ uint32_t foo[1000]; for (foo[0] = 0; foo[0] < 5; ++foo[0]) printf("%d ", foo[0]); }
Esto es asumiendo que se llamará a su matriz de enteros de 32 bits foo
.
for(int i=0;i<=5;i++)
Se permitiría porque está almacenando datosi
?