Votre objectif: étant donné une chaîne de crochets, affichez la distance Damerau-Levenshtein minimale requise pour transformer la chaîne d'entrée en une chaîne où les crochets sont équilibrés.
Contribution
La chaîne d'entrée ne contiendra que des crochets et aucun autre caractère. Autrement dit, il s'agit d'une combinaison de l'un des caractères de (){}[]<>
. Vous pouvez prendre l'entrée sous la forme d'une chaîne ou d'un tableau de caractères. Vous ne pouvez faire aucune autre hypothèse sur la chaîne d'entrée; il peut être arbitrairement long (jusqu'à la taille maximale prise en charge par votre langue), il peut être vide, les crochets peuvent déjà être équilibrés, etc.
Distance Damerau-Levenshtein
La distance Damerau-Levenshtein entre deux chaînes est le nombre minimum d'insertions, de suppressions, de substitutions à un seul caractère et de transpositions (permutation) de deux caractères adjacents.
Sortie
La sortie doit être la distance Damerau-Levenshtein minimale entre la chaîne d'entrée et une chaîne dans laquelle les parenthèses correspondent. La sortie doit être un nombre , pas la chaîne équilibrée résultante.
Une paire de crochets est considérée comme "assortie" si les crochets d'ouverture et de fermeture sont dans le bon ordre et ne contiennent aucun caractère, comme
()
[]{}
Ou si chaque sous-élément à l'intérieur de celui-ci est également mis en correspondance.
[()()()()]
{<[]>}
(()())
Les sous-éléments peuvent également être imbriqués plusieurs couches en profondeur.
[(){<><>[()]}<>()]
<[{((()))}]>
(Merci à @DJMcMayhem pour la définition)
Cas de test
Input Possible Balanced Output
Empty Empty 0
[](){}<> [](){}<> 0
[(){}<> [(){}<>] 1
[(]) []() 1
[[[[[[[[ [][][][] 4
(](<>}[>(}>><(>(({}] ()(<>)[(<><>){}] 7
>]{])< []{()} 3
([)}}>[ (){}<> 4
{<((<<][{{}>[<) <>(<<[]>{}>[]) 5
{><({((})>}}}{(}} {<><({()})>}{}{()} 4
(](<)>}[>(}>>{]<<(]] (<()<><<>()>>[])<()> 9
}})( {}() 2
(Merci à @WheatWizard d'avoir résolu la moitié des cas de test)
C'est du code-golf , le moins d'octets gagne!
Vos soumissions doivent pouvoir être testées, ce qui signifie qu'elles devraient produire un résultat pour chaque cas de test en moins d'une heure.
[<>]
ou[]<>
ou<>
Réponses:
Rétine,
254252264248240232267 octetsMerci à @AnthonyPham, @officialaimm et @MistahFiggins pour avoir signalé les bogues
Essayez-le en ligne!
Solution de force non brute! Il fonctionne pour tous les cas de test et a même trouvé une erreur dans l'un.
-2 octets grâce à @MartinEnder (
${4}
à$+
)+12 octets pour tenir compte des cas d'échange supplémentaires
-16 octets en faisant un meilleur usage des classes de caractères
-8 octets en supprimant une restriction inutile sur l'échange. Cela a également corrigé un bug :)
-10 octets en combinant la logique de permutation en une seule expression régulière
+2 octets pour tenir compte des swaps consécutifs
+ beaucoup pour diverses corrections de bugs **
Explication:
T`[]()`:;'"
est utilisé pour remplacer des types de supports spéciaux pour plus de commodité. Tout d'abord, nous remplaçons récursivement tous les supports correspondants par-
,AB
ou69
selon qu'ils sont adjacents ou non.Ensuite, un "échange" utile est effectué en supprimant les crochets nouvellement appariés et en ajoutant un
1
au début de la chaîne. Nous remplaçons également-
par la chaîne vide, car elle était juste utilisée pour l'échange ci-dessus.Ensuite, nous essayons les «remplacements» en supprimant des paires de crochets sans correspondance qui ne chevauchent pas les crochets déjà appariés et en ajoutant un
1
à la chaîne.Enfin,
\W|6B|1
compte les parenthèses simples restantes plus le nombre de1
s.** Je travaille actuellement sur une version plus courte qui utilise les fonctionnalités de partage de ligne de Retina, bien que j'ai rencontré un problème considérable, donc cela pourrait prendre un certain temps.
la source
${4}
peut être raccourci$+
. Je suis très curieux de savoir pourquoi cela est garanti de fonctionner.[{][}] [] [[][][][][][]] [][][][][][][][][][][][]
, vous pouvez simplement échanger l'}
intérieur de la première paire de parenthèses et l'équilibrer. L'espacement est utilisé pour rendre l'entrée un peu plus lisible. Vous en avez sorti 3 mais ça devrait vraiment en être un.[{]}
renvoie 1 mais[{][]}
renvoie 2.Brain-Flak , 1350 octets
Essayez-le en ligne!
Avec des comparaisons à vitesse constante et un déréférencement de pointeurs, cet algorithme est O (n 3 ). Malheureusement, Brain-Flak n'a ni l'un ni l'autre, donc ce programme s'exécute en temps O (n 5 ) à la place. Le cas de test le plus long prend environ 15 minutes.
Simplifier les résultats
Pour voir que mon algorithme fonctionne, nous devons montrer quelques résultats qui réduisent considérablement l'espace de recherche. Ces résultats reposent sur le fait que la cible est une langue entière au lieu d'une seule chaîne spécifique.
Aucune insertion n'est nécessaire. Au lieu de cela, vous pouvez simplement supprimer le crochet auquel le caractère inséré correspondra éventuellement.
Vous n'aurez jamais besoin de retirer un support, puis d'échanger ses deux voisins. Pour voir cela, supposez wlog que le support supprimé est
(
, nous nous transformonsa(c
doncca
en deux étapes. En modifiantc
et en insérant une copie, nous pouvons atteindreca()
en deux étapes sans échange. (Cette insertion peut ensuite être supprimée par la règle ci-dessus.)Le même support ne devra jamais être échangé deux fois. C'est un fait standard sur la distance Damerau-Levenshtein en général.
Un autre résultat simplifiant que je n'ai pas utilisé, car leur comptabilisation coûterait des octets:
L'algorithme
Lorsqu'une chaîne est réduite à une chaîne équilibrée, l'une des conditions suivantes est vraie:
k
(éventuellement après avoir changé l'un ou les deux).k
.Dans le deuxième cas, le support en position
k
peut avoir échangé avec l'un de ses voisins. Dans l'un ou l'autre de ces deux derniers cas, la chaîne entre la première (éventuellement nouvelle) parenthèse et la parenthèse qui a commencé en positionk
doit être modifiée en une chaîne équilibrée, tout comme la chaîne composée de tout ce qui suitk
.Cela signifie qu'une approche de programmation dynamique peut être utilisée. Puisqu'un crochet échangé n'a pas besoin d'être échangé à nouveau, nous devons seulement considérer les sous-chaînes contiguës, ainsi que les sous-séquences formées en supprimant le deuxième caractère et / ou l'avant-dernier caractère d'une telle sous-chaîne. Par conséquent, il n'y a que O (n 2 ) sous-séquences que nous devons examiner. Chacun d'eux a O (n) façons possibles de faire correspondre (ou supprimer) la première parenthèse, donc l'algorithme serait O (n 3 ) dans les conditions ci-dessus.
La structure des données
La pile de droite comprend les crochets de la chaîne d'origine, avec deux octets par crochet. La première entrée détermine l'intégralité du crochet et est choisie de telle sorte que les crochets correspondants ont une différence d'exactement 1. La deuxième entrée détermine uniquement s'il s'agit d'un crochet d'ouverture ou d'un crochet de fermeture: cela détermine le nombre de modifications nécessaires pour que deux crochets correspondent. L'un et l'autre. Aucun zéro implicite en dessous de ceci n'est jamais rendu explicite, afin que nous puissions utiliser
[]
pour obtenir la longueur totale de cette chaîne.Chaque sous-chaîne considérée est représentée par deux nombres compris entre 0 et 2n: un pour la position de début et un pour la fin. L'interprétation est la suivante:
2k
commencera à la positionk
(indexée 0) et le deuxième caractère n'est pas supprimé.2k+1
commencera à la positionk
et le deuxième caractère est supprimé car il a été échangé vers la gauche.2k
se terminera juste avant la positionk
(c'est-à-dire que la plage est incluse à gauche et à droite uniquement.)2k-1
se terminera juste avant la positionk
, et l'avant-dernier caractère est supprimé car il a été inversé à droite.Certaines plages (
k
àk+1
,2k+1
à2k+1
,2k+1
à2k+3
et2k+1
à2k+5
) n'ont aucun sens physique. Certains d'entre eux apparaissent de toute façon comme des valeurs intermédiaires, car c'est plus facile que d'ajouter des vérifications supplémentaires pour les éviter.La pile de gauche stocke le nombre de modifications nécessaires pour convertir chaque sous-chaîne en une chaîne équilibrée. La distance d'édition pour l'intervalle
(x,y)
est stockée en profondeurx + y(y-1)/2
.Pendant la boucle interne, des entrées sont ajoutées au-dessus de la pile de gauche pour indiquer les mouvements possibles. Ces entrées sont longues de 5 octets. Compter à partir du haut, les chiffres sont
d+1
,y1
,x1
,y2
,x2
, où le mouvement coûted
pas de modifier et divise la sous - chaîne en(x1,y1)
et(x2,y2)
.Le code
Description à venir. Pour l'instant, voici ma copie de travail du code. Certains commentaires peuvent ne pas correspondre à la terminologie.
la source
Haskell , 797 octets
Essayez-le en ligne!
la source