Seu objetivo: Dada uma sequência de colchetes, produza a distância mínima de Damerau-Levenshtein necessária para transformar a sequência de entrada em uma sequência em que os colchetes estejam balanceados.
Entrada
A sequência de entrada conterá apenas colchetes e nenhum outro caractere. Ou seja, é uma combinação de qualquer um dos caracteres (){}[]<>
. Você pode receber a entrada como uma sequência ou uma matriz de caracteres. Você não pode fazer outras suposições sobre a sequência de entrada; pode ser arbitrariamente longo (até o tamanho máximo suportado pelo seu idioma), pode estar vazio, os colchetes já devem estar balanceados etc.
Distância Damerau-Levenshtein
A distância Damerau-Levenshtein entre duas cadeias é o número mínimo de inserções, exclusões, substituições de caracteres únicos e transposições (troca) de dois caracteres adjacentes.
Saída
A saída deve ser a distância mínima de Damerau-Levenshtein entre a sequência de entrada e uma sequência na qual os colchetes são correspondentes. A saída deve ser um número , não a sequência balanceada resultante.
Um par de colchetes é considerado "correspondente" se os colchetes de abertura e fechamento estiverem na ordem correta e não tiverem caracteres dentro deles, como
()
[]{}
Ou se todos os subelementos dentro dele também corresponderem.
[()()()()]
{<[]>}
(()())
Os subelementos também podem ser aninhados em várias camadas de profundidade.
[(){<><>[()]}<>()]
<[{((()))}]>
(Obrigado a @DJMcMayhem pela definição)
Casos de teste
Input Possible Balanced Output
Empty Empty 0
[](){}<> [](){}<> 0
[(){}<> [(){}<>] 1
[(]) []() 1
[[[[[[[[ [][][][] 4
(](<>}[>(}>><(>(({}] ()(<>)[(<><>){}] 7
>]{])< []{()} 3
([)}}>[ (){}<> 4
{<((<<][{{}>[<) <>(<<[]>{}>[]) 5
{><({((})>}}}{(}} {<><({()})>}{}{()} 4
(](<)>}[>(}>>{]<<(]] (<()<><<>()>>[])<()> 9
}})( {}() 2
(Obrigado ao @WheatWizard por resolver metade dos casos de teste)
Isso é código-golfe , o menor número de bytes vence!
Seus envios devem ser testáveis, ou seja, devem gerar um resultado para cada caso de teste em não mais de uma hora.
[<>]
ou[]<>
ou<>
Respostas:
Retina,
254252264248240232267 bytesObrigado a @AnthonyPham, @officialaimm e @MistahFiggins por apontar bugs
Experimente Online!
Solução de força não bruta! Ele funciona para todos os casos de teste e até encontrou um erro em um.
-2 bytes graças a @MartinEnder (
${4}
to$+
)+12 bytes para contabilizar casos de troca adicionais
-16 bytes, fazendo um melhor uso das classes de caracteres
-8 bytes removendo uma restrição desnecessária na troca. Isso também corrigiu um bug :)
-10 bytes combinando a lógica de troca em um único regex
+2 bytes para contabilizar swaps consecutivos
+ muitos para várias correções de bugs **
Explicação:
T`[]()`:;'"
é usado para substituir tipos de suporte especiais por conveniência. Primeiro, substituímos recursivamente todos os colchetes correspondentes por-
,AB
ou69
dependendo de serem adjacentes ou não.Em seguida, a "troca" útil é realizada removendo os colchetes recém-correspondidos e adicionando um
1
ao início da string. Também substituímos-
pela string vazia, pois ela estava sendo usada apenas para a troca acima.Em seguida, tentamos "substituições" removendo pares de colchetes não correspondentes que não se sobrepõem aos colchetes já correspondentes e adicionando um
1
à string.Finalmente,
\W|6B|1
conta todos os colchetes restantes restantes mais o número de1
s.** Atualmente, estou trabalhando em uma versão mais curta que usa os recursos de divisão de linha da Retina, embora tenha tido um problema considerável, por isso pode demorar um pouco.
fonte
${4}
pode ser reduzido para$+
. Estou muito curioso por que isso é garantido que funcione.[{][}] [] [[][][][][][]] [][][][][][][][][][][][]
, você pode simplesmente trocar o}
interior do primeiro par de parênteses e equilibrá-lo. O espaçamento é usado para tornar a entrada um pouco mais legível. Você produziu 3, mas realmente deveria ser um.[{]}
retorna 1, mas[{][]}
retorna 2.Flak cerebral , 1350 bytes
Experimente online!
Com comparações de velocidade constante e desreferenciamento de ponteiro, esse algoritmo é O (n 3 ). Infelizmente, o Brain-Flak não possui nenhum desses, portanto, esse programa é executado no tempo O (n 5 ). O caso de teste mais longo leva cerca de 15 minutos.
Simplificando resultados
Para ver que meu algoritmo funciona, precisamos mostrar alguns resultados que reduzam consideravelmente o espaço de pesquisa. Esses resultados se baseiam no fato de que o destino é um idioma inteiro, em vez de apenas uma sequência específica.
Não são necessárias inserções. Em vez disso, você pode apenas remover o suporte que o caractere inserido acabaria por corresponder.
Você nunca precisará remover um suporte e trocar os dois vizinhos. Para ver isso, assumir WLOG que o suporte removido é
(
, por isso, estamos transformandoa(c
aca
em duas etapas. Ao alterarc
e inserir uma cópia, podemos chegarca()
em duas etapas sem troca. (Essa inserção pode ser removida pela regra acima.)O mesmo suporte nunca precisará ser trocado duas vezes. Este é um fato padrão sobre a distância Damerau-Levenshtein em geral.
Outro resultado simplificador que eu não usei, porque contabilizá-los custaria bytes:
O algoritmo
Quando qualquer string é reduzida a uma string balanceada, uma das seguintes opções será verdadeira:
k
(possivelmente após a alteração de um ou de ambos).k
.No segundo caso, o suporte na posição
k
pode ter sido trocado por um de seus vizinhos. Nos dois últimos casos, a string entre o (possivelmente novo) primeiro colchete e o colchete iniciado na posiçãok
deve ser editada em uma string balanceada, assim como a string que consiste em tudo o que está depoisk
.Isso significa que uma abordagem de programação dinâmica pode ser usada. Como um colchete trocado não precisa ser trocado novamente, precisamos considerar apenas substrings contíguos, bem como subsequências formadas pela remoção do segundo caractere e / ou penúltimo caractere de tal substring. Portanto, existem apenas O (n 2 ) subsequências que precisamos examinar. Cada uma delas possui O (n) maneiras possíveis de corresponder (ou excluir) o primeiro colchete; portanto, o algoritmo seria O (n 3 ) nas condições acima.
A estrutura de dados
A pilha direita inclui os colchetes da sequência original, com dois bytes por colchete. A primeira entrada determina o colchete inteiro e é escolhida de forma que os colchetes correspondentes tenham uma diferença de exatamente 1. A segunda entrada determina apenas se é um colchete de abertura ou um colchete de fechamento: isso determina quantas alterações são necessárias para que dois colchetes correspondam entre si. Nenhum zeros implícito abaixo disso é explicitado, para que possamos usar
[]
para obter o comprimento total dessa string.Cada substring em consideração é representado por dois números no intervalo de 0 a 2n: um para a posição inicial e outro para o final. A interpretação é a seguinte:
2k
começará na posiçãok
(indexada 0) e o segundo caractere não será removido.2k+1
inicia na posiçãok
e o segundo caractere é removido por ter sido trocado para a esquerda.2k
termina antes da posiçãok
(ou seja, o intervalo é inclusivo à esquerda e exclusivo à direita).2k-1
termina antes da posiçãok
e o penúltimo caractere é removido por ter sido trocado para a direita.Alguns intervalos (
k
parak+1
,2k+1
para2k+1
,2k+1
para2k+3
e2k+1
para2k+5
) não fazem sentido físico. De qualquer forma, alguns deles aparecem como valores intermediários, porque é mais fácil do que adicionar verificações adicionais para evitá-los.A pilha esquerda armazena o número de edições necessárias para converter cada substring em uma sequência equilibrada. A distância de edição do intervalo
(x,y)
é armazenada em profundidadex + y(y-1)/2
.Durante o loop interno, as entradas são adicionadas acima da pilha esquerda para indicar quais movimentos são possíveis. Essas entradas têm 5 bytes. Contando a partir do topo, os números são
d+1
,y1
,x1
,y2
,x2
, onde o movimento custad
editar etapas e divide o substring em(x1,y1)
e(x2,y2)
.O código
Descrição para vir. Por enquanto, aqui está minha cópia de trabalho do código. Alguns comentários podem ser inconsistentes com a terminologia.
fonte
Haskell , 797 bytes
Experimente online!
fonte