Remplissez les parenthèses

18

Supports normaux ( (), [], <>et {}) sont agréables et sans ambiguïté, mais quelqu'un a pensé que ce serait une bonne idée d'utiliser des caractères non support comme supports. Ces caractères |et "sont ambigus. Par exemple,

""""

correspondre à

(())

ou

()()

C'est impossible à dire.

Les choses commencent à devenir intéressantes lorsque vous mélangez des types de parenthèses ambiguës, par exemple

"|""||""|"

Pourrait être l'un des suivants

([(([]))]),([()[]()]),([()][()])

Tâche

Votre tâche consiste à prendre une chaîne composée de caractères ambigus et à afficher toutes les chaînes équilibrées possibles que l'auteur aurait pu imaginer.

Plus concrètement, vous sortez toutes les cordes équilibrées qui peuvent être remplacées |par ou [ou ]et "par (ou ). Vous ne devez pas sortir deux fois une chaîne équilibrée.

IO

En entrée, vous devez prendre une chaîne composée de |et ". Si vous souhaitez sélectionner deux caractères distincts autres que |et "pour servir de remplaçants, vous pouvez le faire. Vous devez sortir un conteneur de chaînes équilibrées. Vous pouvez choisir de remplacer []et ()dans la sortie avec les deux autres paires de support ( (), [], <>ou {}) que vous souhaitez. Votre format de sortie doit être cohérent d'une exécution à l'autre.

Notation

Il s'agit de donc les réponses seront notées en octets avec moins d'octets mieux.

Cas de test

"" -> ["()"]
"|"| -> []
||| -> []
"""" -> ["(())","()()"]
""|| -> ["()[]"]
"|"||"|" -> ["([([])])"]    
"|""||""|" -> ["([(([]))])","([()[]()])","([()][()])"]    
Post Rock Garf Hunter
la source
4
attend une réponse de BrainFlak
caird coinheringaahing
Pouvons-nous utiliser des entiers au lieu de chaînes? Qu'en est-il des listes de chiffres ou d'entiers?
Zgarb
@Zgarb Bien sûr, ça va
Post Rock Garf Hunter

Réponses:

7

Python 2 , 135 octets

s=input()
for k in range(2**len(s)):
 try:c=''.join("[]() , ,"[int(c)|k>>i&1::4]for i,c in enumerate(s));eval(c);print c[::2]
 except:0

Essayez-le en ligne!

Attend l'entrée comme 2002au lieu de "||", et entourée de guillemets.

Itère sur les 2 N affectations possibles de "ouvert" et "proche" de la chaîne, créant des chaînes ccomme:

"( [ ( ),],[ ( ),],),( ),"

Si eval-ing cette chaîne lève une exception, elle est inégalée. Sinon, nous imprimons c[::2]en donnant:

([()][()])()
Lynn
la source
6

Rétine , 59 56 55 octets

0`"
<$%">
}0`'
{$%"}
.+
$&_$&
+m`^_|(<>|{})(?=.*_)

A`_

Essayez-le en ligne! Malheureusement, le test de deux ensembles de crochets correspondants dépasse le golfiness d'une seule expression régulière .NET, il économise donc 15 octets à vérifier manuellement. Edit: enregistré 3 4 octets grâce à @ H.PWiz. Explication:

0`"
<$%">

Trouvez un "et faites deux copies de la ligne, une avec un <et une avec un >. Faites-le un "à la fois, de sorte que chacun "double le nombre de lignes.

}0`'
{$%"}

De même avec ', {et }. Ensuite, continuez à remplacer jusqu'à ce que tous les "s et 's sur toutes les copies aient été remplacés.

.+
$&_$&

Faites un double des crochets, séparés par un _.

+m`^_|(<>|{})(?=.*_)

Dans le doublon, supprimez à plusieurs reprises les crochets correspondants, jusqu'à ce qu'il n'en reste plus, auquel cas supprimez-les _également.

A`_

Supprimez toutes les lignes qui ont encore un _.

Rétine , 74 71 70 octets

0`"
<$%">
}0`'
{$%"}
Lm`^(.(?<=(?=\3)(<.*>|{.*}))(?<-3>)|(.))+(?(3)_)$

Essayez-le en ligne! Explication: Les deux premières étapes sont les mêmes que ci-dessus. La troisième étape imprime directement le résultat de la correspondance de deux ensembles de supports correspondants. Cela utilise les groupes d'équilibrage de .NET. À chaque étape de la correspondance, l'expression régulière essaie de faire correspondre un personnage, puis regarde en arrière pour une paire de crochets correspondants, puis vérifie que le haut de la pile correspond au crochet ouvert. S'il peut le faire, cela signifie que le support s'équilibre et que le support ouvert est extrait de la pile. Sinon, l'hypothèse est que nous sommes sur un support ouvert qui doit être poussé vers la pile. Si ces hypothèses ne sont pas vérifiées, la pile ne sera pas vide à la fin et la correspondance échouera.

Approche alternative, également 74 71 octets:

Lm`^((?=(<.*>|{.*})(?<=(.))).|\3(?<-3>))+(?(3)_)$

Ici, nous regardons vers l'avant pour <... >ou {... }, puis regardons derrière pour pousser le support de fermeture sur la pile. Sinon, nous devons faire correspondre et ouvrir le crochet de fermeture que nous avons capturé plus tôt. Dans cette version, l'expression régulière ne parvient même pas à atteindre la fin de la chaîne, mais certaines chaînes telles que celles qui <<<>passeraient à travers le filet si nous ne vérifions pas la présence d'une pile vide.

Neil
la source
1
Vous pouvez économiser quelques octets sur l'échappement en utilisant différents caractères
H.PWiz
@ H.PWiz Ah, je dois avoir oublié ce bit sur l'utilisation de paires de supports alternatifs, merci!
Neil
Vous pouvez également modifier |l'entrée
H.PWiz
2

Husk , 19 octets

fo¬ω`ḞoΣx½¨÷₂¨ΠmSe→

Essayez-le en ligne! Utilise les caractères dsdans l'entrée, les paires de parenthèses correspondantes deet stdans la sortie.

Explication

L'idée est de générer tous les crochets possibles de l'entrée et de conserver ceux qui se réduisent à la chaîne vide lorsque nous supprimons à plusieurs reprises les crochets adjacents. Il ¨÷₂¨s'agit d'une chaîne compressée qui se développe en "dest", qui a été choisie car elle a une forme compressée courte et se compose de paires de caractères avec des points de code adjacents. Le programme est donc équivalent au suivant.

fo¬ω`ḞoΣx½"dest"ΠmSe→  Implicit input, say "ddssdd".
                 m     Map over the string:
                  Se    pair character with
                    →   its successor.
                       Result: ["de","de","st","st","de","de"]
                Π      Cartesian product: ["ddssdd","ddssde",..,"eettee"]
f                      Keep those strings that satisfy this:
                        Consider argument x = "ddsted".
   ω                    Iterate on x until fixed:
         ½"dest"         Split "dest" into two: ["de","st"]
    `Ḟ                   Thread through this list (call the element y):
        x                 Split x on occurrences of y,
      oΣ                  then concatenate.
                          This is done for both "de" and "st" in order.
                        Result is "dd".
 o¬                    Is it empty? No, so "ddsted" is not kept.
                      Result is ["destde","ddstee"], print implicitly on separate lines.
Zgarb
la source
2

Perl, 56 55 53 octets

Comprend +1pourn

utilise [pour []et {pour{}

perl -nE 's%.%"#1$&,+\\$&}"^Xm.v6%eg;eval&&y/+//d+say for< $_>' <<< "[{[[{{[[{["

Génère toutes les possibilités 2 ^ N, puis utilise perl evalpour vérifier si une chaîne comme '+ [+ {}]' est un code valide et si tel est le cas, supprime le +et imprime le résultat

Ton Hospel
la source
1

Clean , 203 186 179 octets

?['(':l][')':t]= ?l t
?['[':l][']':t]= ?l t
?l[h:t]= ?[h:l]t
?[][]=True
?_ _=False
@['"']=[['('],[')']]
@['|']=[['['],[']']]
@[h:t]=[[p:s]\\[p]<- @[h],s<- @t]
$s=[k\\k<- @s| ?[]k]

Essayez-le en ligne!

Utilise uniquement le filtrage de motifs et les compréhensions.

Οurous
la source
1

Perl, 56 octets

Comprend +pourn

Utilise l'entrée [pour la sortie [ou]

Utilise l'entrée {pour la sortie {ou}

perl -nE '/^((.)(?{$^R.$2})(?1)*\2(?{$^R.=$2^v6}))*$(?{say$^R})^/' <<< "[{[[{{[[{["

Utilise un regex étendu perl pour faire correspondre les accolades tout en gardant une trace des choix effectués pendant le retour en arrière. Cela peut être beaucoup plus efficace que de générer tous les candidats 2 ^ N car il rejette déjà de nombreuses affectations impossibles à mi-chemin de la chaîne d'entrée

Ton Hospel
la source
0

Kotlin , 240 236 234 octets

fold(listOf("")){r,c->r.flatMap{i->when(c){'"'->"()".map{i+it}
else->"[]".map{i+it}}}}.filter{val d=ArrayList<Char>()
it.all{fun f(c:Any)=d.size>1&&d.removeAt(0)==c
when(it){')'->f('(')
']'->f('[')
else->{d.add(0,it);1>0}}}&&d.size<1}

Embellie

    fold(listOf("")) {r,c ->
        r.flatMap {i-> when(c) {
            '"'-> "()".map {i+it}
            else -> "[]".map {i+it}
        }}
    }.filter {
        val d = ArrayList<Char>()
        it.all {
            fun f(c:Any)=d.size>1&&d.removeAt(0)==c
            when(it) {
                ')' -> f('(')
                ']' -> f('[')
                else -> {d.add(0,it);1>0}
            }
        } && d.size<1
    }

Tester

private fun String.f(): List<String> =
fold(listOf("")){r,c->r.flatMap{i->when(c){'"'->"()".map{i+it}
else->"[]".map{i+it}}}}.filter{val d=ArrayList<Char>()
it.all{fun f(c:Any)=d.size>1&&d.removeAt(0)==c
when(it){')'->f('(')
']'->f('[')
else->{d.add(0,it);1>0}}}&&d.size<1}

data class Test(val input: String, val outputs: List<String>)

val tests = listOf(
    Test("""""""", listOf("()")),
    Test(""""|"|""", listOf()),
    Test("""|||""", listOf()),
    Test("""""""""", listOf("(())","()()")),
    Test("""""||""", listOf("()[]")),
    Test(""""|"||"|"""", listOf("([([])])")),
    Test(""""|""||""|"""", listOf("([(([]))])","([()[]()])","([()][()])"))
)

fun main(args: Array<String>) {
    for ((input, output) in tests) {
        val actual = input.f().sorted()
        val expected = output.sorted()
        if (actual != expected) {
            throw AssertionError("Wrong answer: $input -> $actual | $expected")
        }
    }

Modifications

jrtapsell
la source
0

C (gcc) , 315 octets

j,b;B(char*S){char*s=calloc(strlen(S)+2,b=1)+1;for(j=0;S[j];b*=(S[j]<62||*--s==60)*(S[j++]-41||*--s==40))S[j]==60?*s++=60:0,S[j]<41?*s++=40:0;return*s>0&*--s<1&b;}f(S,n,k)char*S;{if(n<strlen(S))for(k=2;k--;)S[n]==46-k-k?S[n]=40+k*20,f(S,n+1),S[n]=41+k*21,f(S,-~n),S[n]=46-k-k:0;else B(S)&&puts(S);}F(int*S){f(S,0);}

Essayez-le en ligne!


C (gcc) , 334 octets (ancienne version)

j,b;B(char*S){char*s=calloc(strlen(S)+2,1)+1;for(b=1,j=0;S[j];j++){if(S[j]==60)*s++=60;if(S[j]<41)*s++=40;b*=!(S[j]>61&&*--s!=60)*!(S[j]==41&&*--s!=40);}return*s>0&*--s<1&b;}f(S,n,k)char*S;{if(n>=strlen(S))return B(S)&&puts(S);for(k=0;k<2;k++)S[n]==46-k-k&&(S[n]=40+k*20,f(S,n+1),S[n]=41+k*21,f(S,-~n),S[n]=46-k-k);}F(char*S){f(S,0);}

Essayez-le en ligne!


Explication (ancienne version)

j,b;B(char*S){                   // determine if string is balanced
 char*s=calloc(strlen(S)+2,1)+1; // array to store matching brackets
 for(b=1,j=0;S[j];j++){          // loop through string (character array)
  if(S[j]==60)*s++=60;           // 60 == '<', opening bracket
  if(S[j]<41)*s++=40;            // 40 == '(', opening bracket
  b*=!(S[j]>61&&*--s!=60)*       // 62 == '>', closing bracket
   !(S[j]==41&&*--s!=40);}       // 41 == ')', closing bracket
 return*s>0&*--s<1&b;}           // no unmatched brackets and no brackets left to match
f(S,n,k)char*S;{                 // helper function, recursively guesses brackets
 if(n>=strlen(S))                // string replaced by possible bracket layout
  return B(S)&&puts(S);          // print if balanced, return in all cases
 for(k=0;k<2;k++)                // 46 == '.', guess 40 == '(',
  S[n]==46-k-k&&(S[n]=40+k*20,   //  guess 41 == '(', restore
   f(S,n+1),S[n]=41+k*21,        // 44 == ',', guess 60 == '<',
   f(S,-~n),S[n]=46-k-k);}       //  guess 62 == '>', restore
F(char*S){f(S,0);}               // main function, call helper function

Essayez-le en ligne!

Jonathan Frech
la source
Ne pouvez-vous pas utiliser des tableaux de longueur variable GCC pour vous débarrasser du calloc?
Ton Hospel
@TonHospel J'aurais alors, cependant, soit besoin de convertir le tableau en un pointeur, soit d'introduire une autre variable d'index, que je ne sais pas si cela en vaut la peine, car j'utilise *s++à quelques endroits.
Jonathan Frech
char S[n],*s=Sest toujours plus court quechars*s=calloc(n,1)
Ton Hospel
@TonHospel Je ne sais pas vraiment pourquoi, même si cela ne semble pas fonctionner .
Jonathan Frech
@ceilingcat Merci.
Jonathan Frech