A distância de edição (ou Levenshtein) entre duas seqüências é o número mínimo de inserções, exclusões e substituições de caracteres únicos necessárias para transformar uma sequência em outra. Se as duas seqüências tiverem comprimento n cada, é sabido que isso pode ser feito em O (n ^ 2) por programação dinâmica. O código Python a seguir executa esse cálculo para duas strings s1
e 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]
Nesta tarefa, você precisa se aproximar o máximo possível da distância de edição, mas com uma severa restrição de memória. É permitido ao seu código definir uma matriz contendo 1000 números inteiros de 32 bits e esse deve ser o único armazenamento temporário usado em seu cálculo. Todas as variáveis e estruturas de dados devem estar contidas nessa matriz. Em particular, você não seria capaz de implementar o algoritmo acima, como para cadeias de comprimento 1000, pois seria necessário armazenar pelo menos 1.000.000 de números. Onde sua linguagem não possui números inteiros de 32 bits (por exemplo, Python), basta garantir que você nunca armazene um número maior que 2 ^ 32-1 na matriz.
Você pode ler os dados usando qualquer biblioteca padrão de sua escolha sem se preocupar com as restrições de memória nessa parte. Para tornar a competição justa para a parte principal do seu código, você só pode usar operações que sejam funcionalmente equivalentes às da linguagem de programação C e não pode usar nenhuma biblioteca externa.
Para ficar mais claro, a memória para armazenar os dados de entrada ou usados pelo intérprete de seu idioma, JVM etc. não conta para o seu limite e você não pode gravar nada no disco. Você deve assumir que os dados de entrada são somente leitura quando estão na memória, para não poder reutilizá-los para ganhar mais espaço de trabalho.
O que eu tenho que implementar?
Seu código deve ser lido em um arquivo no seguinte formato. Terá três linhas. A primeira linha é a verdadeira distância de edição. O segundo é a string 1 e o terceiro é a string 2. Vou testá-lo com os dados de amostra em https://bpaste.net/show/6905001d52e8, onde as strings têm comprimento 10.000, mas não devem ser especializadas para esses dados. Ele deve gerar a menor distância de edição possível entre as duas strings.
Você também precisará provar que sua distância de edição é proveniente de um conjunto válido de edições. Seu código deve ter uma opção que o transforme em um modo que possa usar mais memória (o quanto você desejar) e produza as operações de edição que oferecem distância de edição.
Ponto
Sua pontuação será a (optimal edit distance/divided by the edit distance you find) * 100
. Para começar, observe que você pode obter uma pontuação apenas contando o número de incompatibilidades entre as duas cadeias.
Você pode usar qualquer idioma que desejar, disponível gratuitamente e fácil de instalar no Linux.
Desempate
No caso de um tie-break, executarei seu código na minha máquina Linux e o código mais rápido vence.
{ uint32_t foo[1000]; for (foo[0] = 0; foo[0] < 5; ++foo[0]) printf("%d ", foo[0]); }
Isto está assumindo que sua matriz de números inteiros de 32 bits será chamada foo
.
for(int i=0;i<=5;i++)
permitido porque está armazenando dadosi
?