Compila le parentesi


18

Staffe normali ( (), [], <>e {}) sono belle e non ambigua, ma qualcuno ha pensato che sarebbe stata una buona idea quella di utilizzare i caratteri non staffa come parentesi. Questi personaggi |e "sono ambigui. Ad esempio

""""

corrisponde a

(())

o

()()

È impossibile dirlo.

Le cose iniziano a diventare interessanti quando mescoli tipi di parentesi ambigue, per esempio

"|""||""|"

Potrebbe essere uno dei seguenti

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

Compito

Il tuo compito è quello di prendere una stringa fatta di caratteri ambigui e produrre tutte le possibili stringhe bilanciate che l'autore avrebbe potuto intendere.

Più concretamente si uscita tutte le stringhe bilanciate che possono essere fatte sostituzione |sia con [o ]e "sia con (o ). Non dovresti generare due stringhe bilanciate due volte.

IO

Come input dovresti prendere una stringa composta da |e ". Se desideri selezionare due caratteri distinti oltre a |e "fungere da rimpiazzo, puoi farlo. Dovresti generare un contenitore di stringhe bilanciate. Si può scegliere di sostituire []e ()in uscita con altre due coppie di parentesi ( (), [], <>o {}) che si desidera. Il formato di output deve essere coerente su tutte le esecuzioni.

punteggio

Si tratta di quindi le risposte verranno classificate in byte con un numero inferiore di byte migliori.

Casi test

"" -> ["()"]
"|"| -> []
||| -> []
"""" -> ["(())","()()"]
""|| -> ["()[]"]
"|"||"|" -> ["([([])])"]    
"|""||""|" -> ["([(([]))])","([()[]()])","([()][()])"]    

4
attende una risposta BrainFlak
caird coinheringaahing

Possiamo usare numeri interi anziché stringhe? Che dire di elenchi di cifre o numeri interi?
Zgarb,

@Zgarb Certo che va bene
Wheat Wizard

Risposte:


7

Python 2 , 135 byte

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

Provalo online!

Prevede input come 2002invece di "||"e racchiusi tra virgolette.

Scorre tutte le 2 N possibili assegnazioni di "open" e "close" alla stringa, creando stringhe ccome:

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

Se eval-ing questa stringa genera un'eccezione, non ha eguali. In caso contrario, stampiamo c[::2], dando:

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

6

Retina , 59 56 55 byte

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

A`_

Provalo online! Sfortunatamente il test per due set di parentesi corrispondenti supera la golfiness di un singolo regex .NET, quindi consente di risparmiare 15 byte per il controllo manuale. Modifica: salvato 3 4 byte grazie a @ H.PWiz. Spiegazione:

0`"
<$%">

Trova a "e crea due copie della riga, una con a <e una con a >. Fallo uno "alla volta, in modo che ognuno "raddoppi il numero di righe.

}0`'
{$%"}

Allo stesso modo con ', {e }. Quindi, continuate a sostituire fino a quando tutti i "s e 's su tutte le copie sono state sostituite.

.+
$&_$&

Crea un duplicato delle parentesi, separate da a _.

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

Nel duplicato, eliminare ripetutamente le parentesi corrispondenti, fino a quando non ne rimangono più nessuno, nel qual caso eliminare _anche.

A`_

Elimina tutte le righe che hanno ancora un _.

Retina , 74 71 70 byte

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

Provalo online! Spiegazione: le prime due fasi sono come sopra. Il terzo stadio stampa direttamente il risultato della corrispondenza di due serie di parentesi corrispondenti. Questo utilizza i gruppi di bilanciamento di .NET. In ogni fase della partita, la regex cerca di abbinare un personaggio, quindi cerca una coppia di parentesi corrispondenti, quindi controlla che la parte superiore della pila corrisponda alla parentesi aperta. Se può farlo, significa che la parentesi si bilancia e la parentesi aperta viene espulsa dalla pila. Altrimenti, il presupposto è che siamo in una parentesi aperta che deve essere inserita nello stack. Se questi presupposti non valgono, la pila non sarà vuota alla fine e la partita fallirà.

Approccio alternativo, anche 74 71 byte:

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

Qui, guardiamo avanti per <... >o {... }, quindi guardiamo dietro per spingere la staffa di chiusura sulla pila. Altrimenti, dobbiamo abbinare e far apparire la parentesi di chiusura che abbiamo catturato in precedenza. In questa versione il regex potrebbe non arrivare nemmeno alla fine della stringa, ma alcune stringhe come quella <<<>scivolerebbero attraverso la rete se non controllassimo uno stack vuoto.


1
Puoi salvare alcuni byte durante la fuga usando caratteri diversi
H.Pwiz

@ H.PWiz Ah, devo aver ignorato un po 'l'uso delle coppie di parentesi alternative, grazie!
Neil,

È inoltre possibile modificare |l'input
H.Pwiz

2

Buccia , 19 byte

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

Provalo online! Utilizza i caratteri dsnell'input e le coppie di parentesi corrispondenti dee stnell'output.

Spiegazione

L'idea è di generare tutti i possibili bracketing dell'input e mantenere quelli che si riducono alla stringa vuota quando rimuoviamo ripetutamente parentesi adiacenti. La ¨÷₂¨è una stringa compressa che si espande in "dest", che è stato scelto perché ha una forma breve compressa e consiste di coppie di caratteri con Codepoints adiacenti. Pertanto, il programma è equivalente al seguente.

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.

2

Perl, 56 55 53 byte

Include +1pern

utilizza [per []e {per{}

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

Genera tutte le possibilità 2 ^ N, quindi utilizza perl evalper verificare se una stringa come '+ [+ {}]' è un codice valido e, in tal caso, rimuove +e stampa il risultato



1

Pulito , 203 186 179 byte

?['(':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]

Provalo online!

Utilizza solo pattern-matching e comprensioni.


1

Perl, 56 byte

Include +pern

Utilizza input [per output [o]

Utilizza input {per output {o}

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

Utilizza una regex estesa perl per abbinare le parentesi graffe, tenendo traccia delle scelte fatte durante il backtracking. Questo può essere molto più efficiente rispetto alla generazione di tutti i candidati 2 ^ N poiché rifiuta già molti compiti impossibili mentre è in corso attraverso la stringa di input


0

Kotlin , 240 236 234 byte

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}

Abbellire

    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
    }

Test

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")
        }
    }

Le modifiche


0

C (gcc) , 315 byte

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);}

Provalo online!


C (gcc) , 334 byte (vecchia versione)

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);}

Provalo online!


Spiegazione (vecchia versione)

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

Provalo online!


Non è possibile utilizzare matrici a lunghezza variabile GCC per eliminare il calloc?
Ton Hospel,

@TonHospel Avrei quindi bisogno di convertire l'array in un puntatore o di introdurre un'altra variabile indice, che non so se ne valga la pena, dato che sto usando *s++in alcuni punti.
Jonathan Frech,

char S[n],*s=Sè ancora più corto dichars*s=calloc(n,1)
Ton Hospel il

@TonHospel Non so davvero perché, anche se non sembra funzionare .
Jonathan Frech,

@ceilingcat Grazie.
Jonathan Frech,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.