Espansione della staffa!


36

La tua sfida è espandere alcune parentesi nell'input di un programma come mostrato:

  1. Trova una stringa s tra due parentesi corrispondenti [e ], con una singola cifra n dopo la parentesi chiusa.
  2. Rimuovere le staffe.
  3. Sostituisci s con se stesso ripetuto n volte. (Se n è 0, rimuovi semplicemente s .)
  4. Andare al passaggio 1 fino a quando non ci sono più parentesi corrispondenti nell'input.

Ulteriori regole e chiarimenti:

  • Prenderai input e fornirai output con qualsiasi mezzo consentito.
  • È consentita una nuova riga finale nell'output.
  • È sufficiente gestire ASCII stampabile nell'input.
  • Si può presumere che tutte le parentesi corrispondano, ovvero non si riceverà mai l'input []]]]o [[[[].
  • Si può presumere che ogni parentesi di chiusura ]abbia una cifra dopo di essa.

Casi test:

Input                -> Output
[Foo[Bar]3]2         -> FooBarBarBarFooBarBarBar
[one]1[two]2[three]3 -> onetwotwothreethreethree
[three[two[one]1]2]3 -> threetwoonetwoonethreetwoonetwoonethreetwoonetwoone
[!@#[$%^[&*(]2]2]2   -> !@#$%^&*(&*($%^&*(&*(!@#$%^&*(&*($%^&*(&*(
[[foo bar baz]1]1    -> foo bar baz
[only once]12        -> only once2
[only twice]23456789 -> only twiceonly twice3456789
[remove me!]0        -> 
before [in ]2after   -> before in in after

Poiché si tratta di , vince la risposta più breve in ogni lingua. In bocca al lupo!



13
Dovresti pubblicare un'altra sfida per comprimere una stringa nel suo formato più breve
Jo King,

Vale la pena dichiarare esplicitamente che la tua stringa snon dovrebbe mai contenere altre parentesi? Ad esempio, tentare di risolvere [Foo[Bar]3]2espandendo la stringa Foo[Bar3 volte comporterebbe uno stato non validoFoo[BarFoo[BarFoo[Bar]2
BradC

@BradC tutto dipende da come si sceglie di implementare l'attività.
MD XF,

Significa che ci sono due risposte valide a [a[b]2c[d]2e]2? Si ottiene abbcddeabbcddeespandendo be dprima, ma ababcdbcdedbabcdbcdedeespandendo a[be d]2eprima.
BradC,

Risposte:


13

Gema , 17 personaggi

[#]?=@repeat{?;#}

Esecuzione di esempio:

bash-4.4$ gema '[#]?=@repeat{?;#}' <<< '[three[two[one]1]2]3'
threetwoonetwoonethreetwoonetwoonethreetwoonetwoone

Wow, parla di come trovare la lingua giusta per il lavoro!
MD XF

O il lavoro giusto per la lingua. Molte sfide hanno dovuto saltare perché l'argomento ricorsivo non era abbastanza flessibile.
arte

Accettarlo per ora perché non vedo in alcun modo che sta venendo battuto, ma sarà inaccettabile nel caso improbabile che lo faccia.
MD XF,

8

Retina , 24 23 22 byte

+`\[([^][]*)](.)
$2*$1

Provalo online! Questo è praticamente integrato in Retina 1. Modifica: salvato 1 byte grazie a @Kobi. 47 45 byte in Retina 0.8.2:

].
]$&$*¶
{+`\[([^][]*)]¶
$1[$1]
\[([^][]*)]

Provalo online!


7

Haskell , 101 96 byte

fst.(""%)
infix 4%
s%']':d:r=(['1'..d]>>s,r)
s%'[':r|(t,q)<-""%r=s++t%q
s%x:r=s++[x]%r
s%e=(s,e)

Provalo online! Invece di usare espressioni regolari come la maggior parte delle altre risposte, questo implementa un parser ricorsivo.

-5 byte grazie a BMO !


4
Una dichiarazione di fissità per (%)ti fa risparmiare 1 byte e ['1'..d]ti fa risparmiare altri 4, vedi questo .
ბიმო

3
@BMO Bello, non mi aspettavo che una dichiarazione di fissità sarebbe mai stata utile per il golf del codice. Penso che dovresti aggiungerlo alla domanda dei suggerimenti.
Laikoni,

7

Perl 5 , 34 33 29 + 1 ( -p) = 30 byte

s/.([^[]*?)](.)/$1x$2/e&&redo

Provalo online!

Abbattilo con l'aiuto di @Shaggy e @TonHospel.


3
Non conosco la perla ma rifare sembra stupendo!
officialaimm,

Penso che dovresti essere in grado di salvare un byte non sfuggendo a ].
Shaggy,

1
Non conosco Perl ma questo sembra funzionare per 30 + 1 byte.
Shaggy,

2
Questi 29 + 1 funzionano anche: perl -pe 's/.([^[]*?)](.)/$1x$2/e&&redo'eperl -pe 's/.([^][]*)](.)/$1x$2/e&&redo'
Ton Hospel il

5

Japt v2 , 21 20 19 byte

Salvato 2 byte grazie a @Shaggy

e/.([^[]*?)](./@YpZ

Provalo online!

eè la sostituzione ricorsiva, che effettua una sostituzione alla volta fino a quando non ci sono più partite. In questo caso, le corrispondenze della regex /\[([^[]*?)](\d)/gvengono sostituite con <testo interno> ripetute volte <digit> fino a quando non ci sono più corrispondenze.

Secondo quanto ho pianificato ( qui ), questo regex dovrebbe essere più corto di almeno 3 2 byte:

‹[“⁽[»₋”]“.›

2
Come noi " supporre che ogni parentesi di chiusura ]ha una cifra dopo che " si dovrebbe essere in grado di sostituire (\dcon (..
Shaggy,

Puoi anche sostituire \[con.
Shaggy il

@Shaggy Nice, grazie!
ETHproductions

4

JavaScript, 71 67 66 byte

Ho avuto una soluzione 54 byte ma ha ottenuto fregati dal secondo banco di prova! :(

f=s=>s!=(x=s.replace(/.([^[]*?)](.)/,(_,y,z)=>y.repeat(z)))?f(x):x

Casi test

f=s=>s!=(x=s.replace(/.([^[]*?)](.)/,(_,y,z)=>y.repeat(z)))?f(x):x
o.innerText=`[Foo[Bar]3]2
[one]1[two]2[three]3
[three[two[one]1]2]3
[!@#[$%^[&*(]2]2]2
[[foo bar baz]1]1
[only once]12
[only twice]23456789
[remove me!]0
before [in ]2after`.split`\n`.map(x=>x.padEnd(22)+`:  `+f(x)).join`\n`
<pre id=o></pre>



4

Scala , 173 byte

l.foreach{x=>def r(c:String):String={val t="""\[([^\[\]]*)\](.)""".r.unanchored;c match{case t(g,h)=>r(c.replaceAllLiterally(s"[$g]$h",g*h.toInt));case _=>c}};println(r(x))}

Provalo online!

Allargato:

l.foreach { x =>
  def remove(current: String): String = {
    val test ="""\[([^\[\]]*)\](.)""".r.unanchored
    current match {
      case test(g, h) => remove(current.replaceAllLiterally(s"[$g]$h", g * h.toInt))
      case _ => current
    }
  }

  println(remove(x))
}

Vecchia soluzione

Scala , 219 215 213 212 199 byte

l.foreach{x=>def r(c:String):String={"""\[([^\[\]]*)\](.)""".r.findFirstMatchIn(c).map{x=>val g=x.group(1);val h=x.group(2).toInt;r(c.replaceAllLiterally(s"[$g]$h",g*h))}.getOrElse(c)};println(r(x))}

Provalo online!

Allargato:

l.foreach { x =>
  def remove(current: String): String = {
    """\[([^\[\]]*)\](.)""".r.findFirstMatchIn(current).map { x =>
      val g = x.group(1)
      val h = x.group(2).toInt
      remove(current.replaceAllLiterally(s"[$g]$h", g * h))
    }.getOrElse(current)
  }
  println(remove(x))
}

Dove sono la lista delle stringhe che elaboreremo.

Grazie Kevin Cruijssen per -1 byte

È passato da 212 a 199 rimuovendo un parametro inutilizzato, non ha prestato attenzione.


4
Benvenuti in PPCG! Prova l'interprete scala di tio su tio.run/#scala e vedi se puoi inviare un link per la risposta, in modo che altri possano provarlo online. :)
officialaimm,

2
Grazie! Ho modificato la risposta per includere il link. Speriamo che sia giusto come intestazione, codice e piè di pagina siano dichiarati per essere una corretta presentazione.
Shikkou,

1
Ciao, benvenuto in PPCG! Ottima prima risposta, +1 da parte mia. Penso che puoi salvare 1 byte cambiando (\d)in (.), perché sappiamo che una parentesi a blocchi ]è sempre seguita da una cifra.
Kevin Cruijssen,

3

Impilato , 39 38 byte

Salvato 1 byte grazie a Shaggy, ha giocato a golf con regex!

['\[([^[\]]+)](.)'{.y x:x#~y*}recrepl]

Provalo online!

Sostituisce semplicemente in modo ricorsivo una regex '\[([^[\]]+)](.)'con la regola di ripetizione.


I think you can save a byte by not escaping the last ].
Shaggy

3

Python 3, 155 148 101 97 bytes

def f(x):
 a=x.rfind('[')
 if~a:b=x.find(']',a);x=f(x[:a]+x[a+1:b]*int(x[b+1])+x[b+2:])
 return x

Try It Online

Thanks to HyperNeutrino and Mego for -47 bytes and user202729 for -4 bytes.


Make it a one-liner to save a couple bytes: def f(x):a=x.rfind('[');b=x.find(']',a);return f(x[:a]+x[a+1:b]*int(x[b+1])+x[b+2:])if~a else x
mathmandan

3

JavaScript - 77 75 72 bytes

f=a=>a.replace(/(.*)\[([^[]*?)](.)(.*)/,(a,b,c,d,e)=>f(b+c.repeat(d)+e))

Edit: updated regex with Shaggy's recommendation

Snippet:


2
Welcome to PPCG! You can get this down to 70 bytes by tweaking your RegEx.
Shaggy

Yes, 72 bytes, obviously, sorry; I was forgetting to count the f=!
Shaggy

2

QuadR with the argument, 30 28 bytes

\[[^[]+?].
∊(⍎⊃⌽⍵M)⍴⊂1↓¯2↓⍵M

Try it online!

\[[^[]+?]. replace "[non-[ stuff]character" with

¯2↓⍵M drop the last two characters of the Match ("]digit")
1↓ drop the first character ("[")
 enclose to be treated as a whole
()⍴reshape to length:
⌽⍵M reverse the Match
 pick the first (the digit)
 evaluate
ϵnlist (flatten)

 repeat until no more changes happen


The equivalent Dyalog APL function is 47 bytes:

'\[[^[]+?].'R{∊(⍎⊃⌽⍵.Match)⍴⊂1↓¯2↓⍵.Match}⍣≡

Try it online!


2

Java 8, 250 249 241 239 bytes

s->{for(;s.contains("[");)for(int i=0,j,k;i<s.length();)if(s.charAt(i++)==93){String t="",r=t;for(j=k=s.charAt(i)-48;j-->0;)t+=s.replaceAll(r="(.*)\\[([^\\]]+)\\]"+k+"(.*)","$2");s=k<1?t:s.replaceFirst(r,"$1$3").replace("",t);}return s;}

-2 bytes thanks to @JonathanFrech (code contains two unprintable ASCII characters now, which can be seen in the TIO-link below).

Sigh... Java with regex is so damn limited.. I'll just quote myself from another answer here:

Replacing WWWW with 222W is easy in Java, but with 4W not.. If only Java had a way to use the regex capture-group for something.. Getting the length with "$1".length(), replacing the match itself with "$1".replace(...), converting the match to an integer with new Integer("$1"), or using something similar as Retina (i.e. s.replaceAll("(?=(.)\\1)(\\1)+","$#2$1")) or JavaScript (i.e. s.replaceAll("(.)\\1+",m->m.length()+m.charAt(0))) would be my number 1 thing I'd like to see in Java in the future to benefit codegolfing.. >.> I think this is the 10th+ time I hate Java can't do anything with the capture-group match..
Quote from here.

Explanation:

Try it online.

s->{                           // Method with String as both parameter and return-type
  for(;s.contains("[");)       //  Loop as long as the String contains a block-bracket
    for(int i=0,j,k;i<s.length();)
                               //   Inner loop over the characters of the String
      if(s.charAt(i++)==93){   //    If the current character is a closing block-bracket:
        String t="",r=t;       //     Create two temp-Strings, starting empty
        for(j=k=s.charAt(i)-48;//     Take the digit after the closing bracket
            j-->0;)            //     Loop that many times:
          t+=s.replaceAll(r="(.*)\\[([^\\]]+)\\]"+k+"(.*)","$2");
                               //      Append `t` with the word inside the block brackets
        s=k<1?                 //     If the digit was 0:
           t                   //      Replace the input with an empty String as well
          :                    //     Else:
           s.replaceFirst(r,"$1$3").replace("",t);}
                               //      Replace the word between brackets by `t`,
                               //      and remove the digit
  return s;}                   //  Return the modified input-String as result

1
I think you can use a truly ASCII though unprintable character to save two bytes. (Your solution really takes 241 bytes, 239 characters.)
Jonathan Frech

@JonathanFrech Thanks! Was looking for a 1-byte character outside the printable ASCII range. Didn't thought about using an unprintable..
Kevin Cruijssen


2

C, 407 368 bytes

Thanks to Jonathan Frech for saving bytes.

golfed (file bracket.c):

i,j,k,l,n;char*f(a,m)char*a;{for(i=0;a[i];++i){a[i]==91&&(j=i+1);if(a[i]==93){k=a[i+1]-48;if(!k){for(l=i+2;l<m;)a[++l-i+j-4]=a[l];a=realloc(a,m-3);return f(a,m-3);}for(l=j;l<i;)a[~-l++]=a[l];for(l=i+2;l<m;)a[++l-4]=a[l];m-=3;n=m+~-k*(i---j--);a=realloc(a,n);for(l=i;l<m;)a[l+++~-k*(i-j)]=a[l];for(m=0;m<k;++m)for(l=j;l<i;)a[l+++m*(i-j)]=a[l];return f(a,n);}}return a;}

ungolfed with program:

#include <stdlib.h>
#include <stdio.h>

// '[' = 133
// ']' = 135
// '0' = 48

i, j, k, l, n;

char* f(a,m) char*a;
{
  for (i=0; a[i]; ++i) {
    a[i]==91&&(j=i+1);

    if (a[i]==93) {
      k=a[i+1]-48;

      if (!k) {
        for (l=i+2; l<m; )
          a[++l-i+j-4] = a[l];

        a = realloc(a,m-3);
        return f(a,m-3);
      }
      for (l=j;l<i;)
        a[~-l++] = a[l];
      for (l=i+2; l<m; )
        a[++l-4] = a[l];
      m -= 3;
      n = m+~-k*(i---j--);
      a = realloc(a,n);

      for (l=i; l<m; )
        a[l+++~-k*(i-j)] = a[l];
      for (m=0; m<k; ++m)
        for (l=j; l<i;)
          a[l+++m*(i-j)] = a[l];

      return f(a,n);
    }
  }
  return a;
}

int main()
{
  char c[]="[Foo[Bar]3]2";
  char *b;

  char cc[]="[remove me!]0";
  char *bb;

  char ccc[]="[only once]12";
  char *bbb;

  b=malloc(13);
  bb=malloc(14);
  bbb=malloc(14);

  for (i=0; i<13; ++i)
    b[i] = c[i];

  for (i=0; i<14; ++i)
    bb[i] = cc[i];

  for (i=0; i<14; ++i)
    bbb[i]=ccc[i];

  printf("%s\n", f(b, 13));
  printf("%s\n", f(bb, 14));
  printf("%s\n", f(bbb, 14));

  return 0;
}

Compiled with gcc 5.4.1, gcc bracket.c



387 with the needed include (for realloc). I will do a clean update (with the ungolfed version) later. Thanks
Tsathoggua

If you use GCC, I think the compiler will attempt to guess the definition of both malloc and realloc, including stdlib.h by its own.
Jonathan Frech

I didn't know that. Nice feature for code golfing. Thanks.
Tsathoggua

2

Red, 147 bytes

f: func[t][a: charset[not"[]"]while[parse t[any a some[remove["["copy h any a"]"copy d a](insert/dup v: copy""h to-integer d)insert v | skip]]][]t]

Ungolfed:

f: func [t][
    a: charset [not "[]"]                          ; all chars except [ and ]
    while [ parse t [                              ; repeat while parse is returning true
        any a                                      ; 0 or more chars other than [ and ]
        some [                                     ; one or more block:
            remove ["[" copy h any a "]" copy d a] ; remove the entire block, store the
                                                   ; substring between the [] in h,
                                                   ; the digit into d
            (insert/dup v: copy "" h to-integer d) ; makes d copies of h 
            insert v                               ; and inserts them in place 
            | skip ]                               ; skip if no match
        ]                                       
    ][]                                            ; empty block for 'while'
    t                                              ; return the modified string
]

I started learning Red's Parse dialect only yesterday, so I'm sure my code can be improved further. Parse is incomparably more verbose than regex, but is very clear, flexible and readable and can be freely mixed with the rest of the Red language.

Try it online!


1

Jelly, 30 bytes

œṡ”]µḢUœṡ”[ẋ€1¦Ṫ©Ḣ$FṚ;®
Çċ”]$¡

Try it online!


Explanation.


œṡ”]µḢUœṡ”[ẋ€1¦Ṫ©Ḣ$FṚ;®    Helper link 1, expand once.
                           Assume input = "ab[cd]2ef".

œṡ      Split at first occurence of
  ”]      character "]".
    µ   Start new monadic chain. Value = "ab[cd","2ef".

Ḣ       ead. "ab[cd"
 U      Upend. "dc[ba"
  œṡ”[  Split at first occurence of "[". | "dc","ba".

ẋ€        Repeat ...
  1¦        the element at index 1...
          by ...
    Ṫ Ḣ$    the ead of the ail of ...
          the input list ("ab[cd","2ef") (that is, 2)

          The command  also pop the head '2'. The remaining
            part of the tail is "ef".
     ©    Meanwhile, store the tail ("ef") to the register.

          Current value: "dcdc","ba"
FṚ        Flatten and everse. | "abcdcd"
  ;®      Concatenate with the value of the register. "abcdcdef"

Çċ”]$¡    Main link.

 ċ”]$     Count number of "]" in the input.
     ¡    Repeatedly apply...
Ç           the last link...
            that many times.

1

C,381 bytes

Compact version:

while(1){int t=strlen(i);int a,c=-1;char*w;char*s;char*f;while(c++<t){if(i[c]==']'){int k=c-a;w=calloc((k--),1);memcpy(w,&i[a+1],k);s=calloc((t-c-1),1);memcpy(s,&i[c+2],t-c-2);i[a]=0;int r=i[c+1]-48;if(r==0){f=calloc(t,1);sprintf(f,"%s%s",i,s);}else{f=calloc((t+k),1);sprintf(f,"%s%s[%s]%d%s",i,w,w,r-1,s);}free(i);i=f;break;}else if(i[c]=='[')a=c;}free(w);free(s);if(c>=t)break;}

Full version:

#include <string.h>
#include <stdio.h>
#include <stdlib.h>

void proceed(char* input)
{
  while(1)
  {
    int t=strlen(input);
    int start,cursor=-1;
    char* word;
    char* suffix;
    char* final;
    while(cursor++<t)
    {
      if(input[cursor]==']')
      {
        int wordlength = cursor-start;
        word=calloc((wordlength--),sizeof(char));
        memcpy(word, &input[start+1], wordlength );
        suffix=calloc((t-cursor-1),sizeof(char));
        memcpy( suffix, &input[cursor+2], t-cursor-2 );
        input[start]='\0';
        int rep=input[cursor+1]-'0';
        if(rep==0)
        {
          final=calloc(t,sizeof(char));
          sprintf(final,"%s%s",input,suffix);
        }
        else
        {
          final=calloc((t+wordlength+5),sizeof(char));
          sprintf(final,"%s%s[%s]%d%s",input,word,word,rep-1,suffix);
        }
        free(input);
        input=final;
        break;
      }
      else if(input[cursor]=='[')
        start=cursor;
    }
    free(word);
    free(suffix);

    if(cursor>=t)break;
  }
}

int main()
{
  char* input=calloc(256,sizeof(char));
  sprintf(input,"a[[toto]2b]2[ana]3");
  printf("in : %s\n",input);
  proceed(input);
  printf("out: %s\n",input);
  return 0;
}

3
Welcome to PPCG!
Shaggy

1
Welcome to the site! Note that C submissions need to be full programs or functions, not just snippets.
MD XF

1

Python, 80 bytes

import re
b=re.sub
s=lambda x:eval(b(r"\](.)",r"')*\1+'",b(r"\[","'+('","%r"%x)))

Try it online!

s("[Foo[Bar]3]2") Converts [Foo[Bar]3]2 to ''+('Foo'+('Bar')*3+'')*2+'', and evaluates.

Fails for input with quotes in brackets (e.g. [']3)


I downvoted this answer as the question requires handling any printable ASCII in the input, and this answer doesn't. Notify me if you fix it, and I'll happily retract my vote.
caird coinheringaahing
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.