# Bracket Expansion!

Your challenge is to expand some brackets in a program's input as shown:

1. Find a string s between two matching brackets [ and ], with a single digit n after the closing bracket.
2. Remove the brackets.
3. Replace s with itself repeated n times. (If n is 0, simply remove s.)
4. Go to step 1 until there are no more matching brackets in the input.

• You will take input and give output via any allowed means.
• A trailing newline in the output is allowed.
• You only need to handle printable ASCII in the input.
• You may assume that all brackets match, i.e. you will never receive the input []]]] or [[[[].
• You may assume that each closing bracket ] has a digit after it.

Test cases:

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  As this is , the shortest answer in each language wins. Good luck! • – MD XF Jan 30 '18 at 2:24 • You should post another challenge to compress a string back down to its shortest format – Jo King Jan 30 '18 at 9:11 • Is it worth stating explicitly that your string s should never contain other brackets? For example, attempting to solve [Foo[Bar]3]2 by expanding the string Foo[Bar 3 times would result in an invalid state Foo[BarFoo[BarFoo[Bar]2 – BradC Jan 30 '18 at 20:17 • @BradC that all depends on how you choose to implement the task. – MD XF Jan 30 '18 at 21:59 • Does that mean that there are two valid answers to [a[b]2c[d]2e]2? You get abbcddeabbcdde by expanding b and d first, but ababcdbcdedbabcdbcdede by expanding a[b and d]2e first. – BradC Jan 30 '18 at 22:23 ## 19 Answers # Gema, 17 characters [#]?=@repeat{?;#}  Sample run: bash-4.4$ gema '[#]?=@repeat{?;#}' <<< '[three[two[one]1]2]3'
threetwoonetwoonethreetwoonetwoonethreetwoonetwoone

• Wow, talk about finding the right language for the job! – MD XF Jan 31 '18 at 2:00
• Or the right job for the language. Many challenges had to skip because the recursive argument was not flexible enough. – manatwork Jan 31 '18 at 8:57
• Accepting this for now cause I don't see any way it's getting beat, but it'll be unaccepted in the unlikely case that it does. – MD XF Feb 2 '18 at 3:59

# Retina, 2423 22 bytes

+$([^][]*)](.) 2*1  Try it online! This is practically a builtin in Retina 1. Edit: Saved 1 byte thanks to @Kobi. 47 45 bytes in Retina 0.8.2: ]. ]&*¶ {+$$([^][]*)]¶ 1[1] \[([^][]*)]  Try it online! # Haskell, 101 96 bytes 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)  Try it online! Instead of using regular expression like most of the other answers, this implements a recursive parser. -5 bytes thanks to BMO! • A fixity declaration for (%) saves you 1 byte and ['1'..d] saves you another 4, see this. – ბიმო Jan 30 '18 at 8:12 • @BMO Nice, I didn't expect a fixity declaration would ever be useful for code golfing. I think you should add that to the tips question. – Laikoni Jan 30 '18 at 8:39 # Perl 5, 3433 29 + 1 (-p) = 30 bytes s/.([^[]*?)](.)/1x2/e&&redo  Try it online! Cut it down with some help from @Shaggy and @TonHospel. • I don't know pearl but redo seems gorgeous! – officialaimm Jan 30 '18 at 4:02 • I think you should be able to save a byte by not escaping the ]. – Shaggy Jan 30 '18 at 11:05 • I don't know Perl but this seems to work for 30+1 bytes. – Shaggy Jan 30 '18 at 11:12 • These 29+1 also work: perl -pe 's/.([^[]*?)](.)/1x2/e&&redo' and perl -pe 's/.([^][]*)](.)/1x2/e&&redo' – Ton Hospel Jan 30 '18 at 15:07 # Japt v2, 2120 19 bytes Saved 2 bytes thanks to @Shaggy e/.([^[]*?)](./@YpZ  Test it online! e is recursive replace, which makes one replacement at a time until there are no more matches. In this case, matches of the regex /\[([^[]*?)](\d)/g are replaced with with <inner text> repeated <digit> times until there are no more matches. According to what I have planned (here), this regex should eventually be at least 3 2 bytes shorter: ‹[“⁽[»₋”]“.›  • As we "may assume that each closing bracket ] has a digit after it" you should be able to replace (\d with (.. – Shaggy Jan 30 '18 at 8:19 • You can also replace \[ with . – Shaggy Jan 30 '18 at 19:27 • @Shaggy Nice, thanks! – ETHproductions Jan 30 '18 at 23:05 # JavaScript, 7167 66 bytes I had a 54 byte solution but it got screwed over by the second test case! :( f=s=>s!=(x=s.replace(/.([^[]*?)](.)/,(_,y,z)=>y.repeat(z)))?f(x):x  ## Test Cases 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> # Python 3, 11093 92 bytes import re f=lambda s:f(re.sub(r'\[([^][]+)$(.)',lambda m:m[1]*int(m[2]),s))if'['in s else s  Try it online! -17 bytes thanks to pizzapants184 -1 byte thanks to Kevin Cruijssen • -17 bytes in Python 3 with re.match indexing and substring check using in. – pizzapants184 Jan 30 '18 at 18:12 • -1 byte by changing (\d) to (.), because we know a block-bracket ] is always followed by a digit. – Kevin Cruijssen Feb 1 '18 at 12:28 # Scala, 173 bytes 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))}


Try it online!

### Expanded:

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


# Scala, 219215213212199 bytes

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


Try it online!

### Expanded:

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


Where l is the list of strings that we will process.

Thanks Kevin Cruijssen for -1 byte

Went from 212 to 199 by removing an unused parameter, didn't pay attention.

• Welcome to PPCG! Try tio's scala interpreter at tio.run/#scala and see if you can submit a link for the answer, so that others can try it online. :) – officialaimm Jan 31 '18 at 9:16
• Thank you! I edited the answer to include the link. Hopefully it is ok how the header, code and footer is declared in order to be a proper submission. – Shikkou Jan 31 '18 at 10:17
• Hi, welcome to PPCG! Great first answer, +1 from me. I think you can save 1 byte by changing (\d) to (.), because we know a block-bracket ] is always followed by a digit. – Kevin Cruijssen Feb 1 '18 at 12:26

# Stacked, 39 38 bytes

Saved 1 byte thanks to Shaggy, golfed the regex!

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


Try it online!

Simply recursively replaces a regex '$([^[$]+)](.)' with the repetition rule.

• I think you can save a byte by not escaping the last ]. – Shaggy Jan 30 '18 at 11:15

# Python 3, 155148101 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 Jan 31 '18 at 23:01

f=a=>a.replace(/(.*)$([^[]*?)](.)(.*)/,(a,b,c,d,e)=>f(b+c.repeat(d)+e))  Edit: updated regex with Shaggy's recommendation Snippet: const test = ["[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"]; const f=a=>a.replace(/(.*)$$([^[]*?)](.)(.*)/,(a,b,c,d,e)=>f(b+c.repeat(d)+e)) d.innerHTML=test.map(f).join("<br>"); <p id="d"> • Welcome to PPCG! You can get this down to 70 bytes by tweaking your RegEx. – Shaggy Jan 31 '18 at 10:21 • Yes, 72 bytes, obviously, sorry; I was forgetting to count the f=! – Shaggy Feb 1 '18 at 17:40 # 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! # Java 8, 250249241 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="(.*)\$([^$$/extract_itex]]+)\$$"+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  • 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 Jan 30 '18 at 18:54 • @JonathanFrech Thanks! Was looking for a 1-byte character outside the printable ASCII range. Didn't thought about using an unprintable.. – Kevin Cruijssen Jan 31 '18 at 7:54 # Wolfram Language (Mathematica), 86 bytes #//.s_:>StringReplace[s,"["~~x:Except["["|"]"]...~~"]"~~d_:>""<>x~Table~FromDigits@d]&  Try it online! # 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 • – Jonathan Frech Jan 31 '18 at 18:16 • 387 with the needed include (for realloc). I will do a clean update (with the ungolfed version) later. Thanks – Tsathoggua Feb 1 '18 at 6:54 • 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 Feb 1 '18 at 12:06 • I didn't know that. Nice feature for code golfing. Thanks. – Tsathoggua Feb 2 '18 at 7:12 # 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! # 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".

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...
that many times.


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

• Welcome to PPCG! – Shaggy Jan 30 '18 at 16:57
• Welcome to the site! Note that C submissions need to be full programs or functions, not just snippets. – MD XF Jan 30 '18 at 22:12

## 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 Feb 2 '18 at 16:32