Generate all Brain-Flak Snippets

14

This question is the second of several Brain-flak Birthday challenges designed to celebrate Brain-Flak's first Birthday! You can find more information about Brain-Flak's Birthday here

Challenge

For this challenge you'll be generating all fully matched strings from a list of brackets. To borrow DJMcMayhem's definition of a fully matched string:

  • For the purpose of this challenge, a "bracket" is any of these characters: ()[]{}<>.

  • A pair of brackets is considered "matched" if the opening and closing brackets are in the right order and have no characters inside of them, such as

    ()
    []{}
    

    Or if every subelement inside of it is also matched.

    [()()()()]
    {<[]>}
    (()())
    

    Subelements can also be nested several layers deep.

    [(){<><>[()]}<>()]
    <[{((()))}]>
    
  • A string is considered "Fully matched" if and only if each pair of brackets has the correct opening and closing bracket in the right order.


Input

Your program or function will take a list of four non-negative numbers in any convenient, consistent format. This includes (but is not limited to) a list of integers, a non-digit delimited string, or separate arguments. These four numbers represent the number of matched pairs of each type of bracket. For example, [1,2,3,4] would represent:

  • 1 pair of ()

  • 2 pairs of {}

  • 3 pairs of [] and

  • 4 pairs of <>

You may choose which pair of brackets each input corresponds to as long as it is consistent.

Output

You should output all fully matched string that can be formed from this list of brackets without duplicates. Output can be in any reasonable format which includes printing a non-bracket delimited string to STDOUT, or a list of strings as a return value from a function.

Your algorithm must work for any arbitrary input, but you don't need to worry about memory, time or integer size limits (e.g. if your answer is in C you won't get 233 as an input).

This is , so the shortest answer in bytes wins.

Example Input and Output

For these example I will use the same input order as above.

For each example, the first line will be input and the following lines will be the output

Example 0:
[0,0,0,0]


Example 1:
[1,0,0,0]
()

Example 2:
[0,2,0,0]
{}{}
{{}}

Example 3:
[0,0,1,1]
[]<>
[<>]
<[]>
<>[]

Example 4:
[0,1,2,0]
{}[][]  {}[[]]  {[]}[]  {[][]}  {[[]]} 
[{}][]  [{}[]]  [{[]}]  []{}[]  []{[]} 
[][{}]  [][]{}  [[{}]]  [[]{}]  [[]]{}

Example 5:
[1,0,0,3]
()<><><>  ()<><<>>  ()<<>><>  ()<<><>>  ()<<<>>>  (<>)<><>  (<>)<<>>
(<><>)<>  (<><><>)  (<><<>>)  (<<>>)<>  (<<>><>)  (<<><>>)  (<<<>>>)
<()><><>  <()><<>>  <()<>><>  <()<><>>  <()<<>>>  <(<>)><>  <(<>)<>>
<(<><>)>  <(<<>>)>  <>()<><>  <>()<<>>  <>(<>)<>  <>(<><>)  <>(<<>>)
<><()><>  <><()<>>  <><(<>)>  <><>()<>  <><>(<>)  <><><()>  <><><>()
<><<()>>  <><<>()>  <><<>>()  <<()>><>  <<()><>>  <<()<>>>  <<(<>)>>
<<>()><>  <<>()<>>  <<>(<>)>  <<>>()<>  <<>>(<>)  <<>><()>  <<>><>()
<<><()>>  <<><>()>  <<><>>()  <<<()>>>  <<<>()>>  <<<>>()>  <<<>>>()

Example 6:
[1,1,1,1]

(){}[]<>  (){}[<>]  (){}<[]>  (){}<>[]  (){[]}<>  (){[]<>}  (){[<>]}
(){<[]>}  (){<>}[]  (){<>[]}  ()[{}]<>  ()[{}<>]  ()[{<>}]  ()[]{}<>
()[]{<>}  ()[]<{}>  ()[]<>{}  ()[<{}>]  ()[<>{}]  ()[<>]{}  ()<{}[]>
()<{}>[]  ()<{[]}>  ()<[{}]>  ()<[]{}>  ()<[]>{}  ()<>{}[]  ()<>{[]}
()<>[{}]  ()<>[]{}  ({})[]<>  ({})[<>]  ({})<[]>  ({})<>[]  ({}[])<>
({}[]<>)  ({}[<>])  ({}<[]>)  ({}<>)[]  ({}<>[])  ({[]})<>  ({[]}<>)
({[]<>})  ({[<>]})  ({<[]>})  ({<>})[]  ({<>}[])  ({<>[]})  ([{}])<>
([{}]<>)  ([{}<>])  ([{<>}])  ([]){}<>  ([]){<>}  ([])<{}>  ([])<>{}
([]{})<>  ([]{}<>)  ([]{<>})  ([]<{}>)  ([]<>){}  ([]<>{})  ([<{}>])
([<>{}])  ([<>]){}  ([<>]{})  (<{}[]>)  (<{}>)[]  (<{}>[])  (<{[]}>)
(<[{}]>)  (<[]{}>)  (<[]>){}  (<[]>{})  (<>){}[]  (<>){[]}  (<>)[{}]
(<>)[]{}  (<>{})[]  (<>{}[])  (<>{[]})  (<>[{}])  (<>[]){}  (<>[]{})
{()}[]<>  {()}[<>]  {()}<[]>  {()}<>[]  {()[]}<>  {()[]<>}  {()[<>]}
{()<[]>}  {()<>}[]  {()<>[]}  {([])}<>  {([])<>}  {([]<>)}  {([<>])}
{(<[]>)}  {(<>)}[]  {(<>)[]}  {(<>[])}  {}()[]<>  {}()[<>]  {}()<[]>
{}()<>[]  {}([])<>  {}([]<>)  {}([<>])  {}(<[]>)  {}(<>)[]  {}(<>[])
{}[()]<>  {}[()<>]  {}[(<>)]  {}[]()<>  {}[](<>)  {}[]<()>  {}[]<>()
{}[<()>]  {}[<>()]  {}[<>]()  {}<()[]>  {}<()>[]  {}<([])>  {}<[()]>
{}<[]()>  {}<[]>()  {}<>()[]  {}<>([])  {}<>[()]  {}<>[]()  {[()]}<>
{[()]<>}  {[()<>]}  {[(<>)]}  {[]()}<>  {[]()<>}  {[](<>)}  {[]}()<>
{[]}(<>)  {[]}<()>  {[]}<>()  {[]<()>}  {[]<>()}  {[]<>}()  {[<()>]}
{[<>()]}  {[<>]()}  {[<>]}()  {<()[]>}  {<()>}[]  {<()>[]}  {<([])>}
{<[()]>}  {<[]()>}  {<[]>()}  {<[]>}()  {<>()}[]  {<>()[]}  {<>([])}
{<>}()[]  {<>}([])  {<>}[()]  {<>}[]()  {<>[()]}  {<>[]()}  {<>[]}()
[(){}]<>  [(){}<>]  [(){<>}]  [()]{}<>  [()]{<>}  [()]<{}>  [()]<>{}
[()<{}>]  [()<>{}]  [()<>]{}  [({})]<>  [({})<>]  [({}<>)]  [({<>})]
[(<{}>)]  [(<>){}]  [(<>)]{}  [(<>{})]  [{()}]<>  [{()}<>]  [{()<>}]
[{(<>)}]  [{}()]<>  [{}()<>]  [{}(<>)]  [{}]()<>  [{}](<>)  [{}]<()>
[{}]<>()  [{}<()>]  [{}<>()]  [{}<>]()  [{<()>}]  [{<>()}]  [{<>}()]
[{<>}]()  [](){}<>  [](){<>}  []()<{}>  []()<>{}  []({})<>  []({}<>)
[]({<>})  [](<{}>)  [](<>){}  [](<>{})  []{()}<>  []{()<>}  []{(<>)}
[]{}()<>  []{}(<>)  []{}<()>  []{}<>()  []{<()>}  []{<>()}  []{<>}()
[]<(){}>  []<()>{}  []<({})>  []<{()}>  []<{}()>  []<{}>()  []<>(){}
[]<>({})  []<>{()}  []<>{}()  [<(){}>]  [<()>{}]  [<()>]{}  [<({})>]
[<{()}>]  [<{}()>]  [<{}>()]  [<{}>]()  [<>(){}]  [<>()]{}  [<>({})]
[<>{()}]  [<>{}()]  [<>{}]()  [<>](){}  [<>]({})  [<>]{()}  [<>]{}()
<(){}[]>  <(){}>[]  <(){[]}>  <()[{}]>  <()[]{}>  <()[]>{}  <()>{}[]
<()>{[]}  <()>[{}]  <()>[]{}  <({})[]>  <({})>[]  <({}[])>  <({[]})>
<([{}])>  <([]){}>  <([])>{}  <([]{})>  <{()}[]>  <{()}>[]  <{()[]}>
<{([])}>  <{}()[]>  <{}()>[]  <{}([])>  <{}[()]>  <{}[]()>  <{}[]>()
<{}>()[]  <{}>([])  <{}>[()]  <{}>[]()  <{[()]}>  <{[]()}>  <{[]}()>
<{[]}>()  <[(){}]>  <[()]{}>  <[()]>{}  <[({})]>  <[{()}]>  <[{}()]>
<[{}]()>  <[{}]>()  <[](){}>  <[]()>{}  <[]({})>  <[]{()}>  <[]{}()>
<[]{}>()  <[]>(){}  <[]>({})  <[]>{()}  <[]>{}()  <>(){}[]  <>(){[]}
<>()[{}]  <>()[]{}  <>({})[]  <>({}[])  <>({[]})  <>([{}])  <>([]){}
<>([]{})  <>{()}[]  <>{()[]}  <>{([])}  <>{}()[]  <>{}([])  <>{}[()]
<>{}[]()  <>{[()]}  <>{[]()}  <>{[]}()  <>[(){}]  <>[()]{}  <>[({})]
<>[{()}]  <>[{}()]  <>[{}]()  <>[](){}  <>[]({})  <>[]{()}  <>[]{}()

Riley

Posted 2017-04-27T18:13:10.153

Reputation: 11 345

Related – Riley – 2017-04-27T18:13:47.667

Answers

6

Haskell, 128 bytes

f is the main function, it takes a list of Ints and returns a list of Strings.

f=g.($zip"({[<"")}]>").zipWith replicate
g=max[""].(#g)
l#c=[b:s|x@(b,e):r<-l,s<-(r:filter(/=x:r)l)?(map(e:).c)]
l?c=c l++l#(?c)

Try it online!

How it works

  • f transforms its input list into a list of lists of tuples, each tuple containing a bracket pair, with each type of bracket in its own sublist. E.g. [1,2,0,0] becomes [[('{','}')],[('[',']'),('[',']')]]. Then it calls g with the transformed list.
  • The remaining functions use a partially continuation-passing style intermingled with list manipulation. Each continuation function c takes a list l of remaining bracket tuple lists and returns a list of possible strings to be suffixed to what's already been generated.
  • g l generates the list of fully matched strings formable by using all the brackets in l.
    • It does this by calling l#g to generate strings beginning with some bracket. The recursive g parameter is itself used as a continuation by #, to generate what comes after the first bracketed subelement.
    • In the case where there are no such strings (because l has no brackets left inside) g instead returns [""], the list containing just the empty string. Since [""] compares smaller to all nonempty lists produceable by #, we can do this by applying max.
  • l#c generates strings from l beginning with at least one bracketed subelement, leaving to the continuation c to determine what follows the element.
    • b and e are a selected pair of brackets in the tuple x, and r is the list of remaining tuples of the same bracket type.
    • r:filter(/=x:r)l is l with the tuple x removed, slightly rearranged.
    • ? is called to generate the possible subelements between b and e. It gets its own continuation map(e:).c, which prefixes e to each of the suffix strings generated by c.
    • # itself prepends the initial b to all the strings generated by ? and c.
  • l?c generates the fully matched strings formable by using zero or more bracket pairs from l, and then leaves to its continuation c to handle what's left over. The c l part goes directly to c without adding any subelements, while l#(?c) uses # to generate one subelement and then call (?c) recursively for possible further ones.

Ørjan Johansen

Posted 2017-04-27T18:13:10.153

Reputation: 6 914

4

Jelly, 50 40 34 bytes

-6 bytes thanks to Leaky Nun (getting reduce to work where I couldn't)

“()“{}“[]“<>”©ẋ"FŒ!QµW;®œṣF¥/µÐLÐḟ

Plain and inefficient.

Try it online! (times out at TIO for [1,1,1,1] - yes, inefficient.)

How?

Recursively removes pairs of matching brackets that reside right next to each other until no more may be removed for every possible string one may form, keeping such strings which reduce to nothing (hence have all matching content).

“()“{}“[]“<>”©ẋ"FŒ!QµW;®œṣF¥/µÐLÐḟ - Main link: list: [n(), n{}, n[], n<>]
“()“{}“[]“<>”                      - literal ["()", "{}", "[]", "<>"]
             ©                     - copy to register
               "                   - zip with:
              ẋ                    -   repeat list
                F                  - flatten
                 Œ!                - all permutations (yeah, it's inefficient!)
                   Q               - de-duplicate
                    µ              - monadic chain separation
                                Ðḟ - filter discard if (non empty is truthy):
                             µÐL   -   loop until no change:
                       ®           -     recall value from register
                     W             -     wrap loop variable in a list
                      ;            -     concatenate
                           ¥/      -     reduce with last two links as a dyad:
                        œṣ         -       split left on occurrences of sublist on the right
                          F        -       flatten the result

Jonathan Allan

Posted 2017-04-27T18:13:10.153

Reputation: 67 804

1

No need to use eval tricks... use reduce instead. 35 bytes

– Leaky Nun – 2017-04-28T04:17:55.337

1

Moving the first line to the second... 34 bytes

– Leaky Nun – 2017-04-28T04:20:19.063

@LeakyNun Thanks! I tried but couldn't get a reduce to work (hence resorted to using eval). – Jonathan Allan – 2017-04-28T04:41:15.920

Nice, I used the same approach of œṣ-F-µÐL in a somewhat related problem.

– Zacharý – 2017-09-09T21:43:32.437

3

Pyth - 83 74 71 63 bytes

K("\[]""{}""\(\)""<>")Fd{.psm*:@Kd*\\2k@QdU4JdVldFHK=:JHk))I!Jd

Try It

1: Kc"[] {} () <>")Fd{.ps*V-R\KQJdVldFHK=:JHk))I!Jd

Also, this 53-byte version thanks to Leaky Nun

Kc"\[] \{} \(\) <>")Fd{.ps*V-R\\KQJdVldFHK=:JHk))I!Jd

Here

Maria

Posted 2017-04-27T18:13:10.153

Reputation: 644

Jelly beaten by Pyth? What is this sorcery? – math junkie – 2017-04-27T23:45:18.303

@mathjunkie I didn't beat Jelly; I screwed up the input syntax. – Maria – 2017-04-28T00:08:38.123

...and I think I can improve :D – Jonathan Allan – 2017-04-28T00:20:05.363

@JonathanAllan so can this answer. – Leaky Nun – 2017-04-28T03:39:00.970

1

Step 1: instead of ("\[]""{}""\(\)""<>"), we do c"\[] \{} \(\) <>") (split on whitespace); instead of :@Kd*\\2k, we do -@Kd followed by two backslashes; then, instead of mapping on U4, we do *V-R\\KQ (multiply two arrays in parallel). The first array is generated using R, namely -R\\k This will give you a 54-byte version

– Leaky Nun – 2017-04-28T03:43:24.043

A note: I hope that you know you can use V in a nested manner. The variable changes from N to H and then to b as you go into a deeper level. It is documented. – Leaky Nun – 2017-04-28T03:46:03.340

Step 2: We use u (reduce) two times. The first time is a fixed-point, i.e. do the substitutions repeatedly until there is no change. The second layer inside where we do the substitution also require reduce, as we have 4 substitutions to do one-by-one. Also, we use V instead of F. This would give you a 46-byte version.

– Leaky Nun – 2017-04-28T03:49:46.790

Step 3: instead of using a for-loop and printing when a condition is satisfied, we use f to filter those who satisfy the condition, i.e. V[array]I[condition]N becomes f[condition][array]. This also changes the output format to a list of strings. Now, instead of storing an escaped string, we store an unescaped string and escape it in regex. This makes each component of the string 2 letters long, which allows us to do c"[]{}()<>"2. 37-byte version

– Leaky Nun – 2017-04-28T03:56:45.210

Step 4: instead of building a regex to replace, we don't use regex at all. Notice that replace(a,b,"") is essentially the same as join(split(a,b)). This would give you a 32-byte version.

– Leaky Nun – 2017-04-28T04:27:04.070

@LeakyNun wow nice. – Jonathan Allan – 2017-04-28T05:03:55.257

@JonathanAllan the "split-and-join" alternative to regex-replacing is inspired by your answer :p – Leaky Nun – 2017-04-28T06:13:37.217

2

Ruby, 123 bytes

->a{"<>{}[]()".gsub(/../){$&*a.pop}.chars.permutation.map(&:join).uniq.grep /^((\(\g<1>\)|\[\g<1>\]|\{\g<1>\}|<\g<1>>)*)$/}

Try it online! It's inefficient, though, so even inputs like [1,2,1,1] will time out online. All the listed examples will work, at least!

Explanation

->a{                                        # Procedure with input a
    "<>{}[]()".gsub(/../){                  # For all pairs of brackets
                          $&*a.pop          # Pop last item in input, then repeat
                                            #   the bracket pair by that number
                                  }.chars   # Get characters
        .permutation                        # All permutations of characters
                    .map(&:join)            # For each permutation, join the chars
                                .uniq       # Get unique permutations only
            .grep /^((\(\g<1>\)|\[\g<1>\]|\{\g<1>\}|<\g<1>>)*)$/}
                                            # Only return permutations that match
                                            #   this bracket-matching regex

Value Ink

Posted 2017-04-27T18:13:10.153

Reputation: 10 608

2

05AB1E, 33 32 30 27 25 bytes

Saved 7 bytes thanks to Riley.

Input order is [(),<>,[],{}]

žu4äשJœJÙD[D®õ:DŠQ#]€g_Ï

Try it online!

Explanation

žu                             # push the string "()<>[]{}"
  4ä                           # split in 4 parts
    ©                          # store a copy in register
     ×                         # repeat each bracket a number of times decided by input
      JœJÙ                     # get the unique permutations of the string of brackets
          D                    # duplicate
           [                   # start infinite loop
            D                  # duplicate current list of permutations
             ®õ:               # replace any instance of (), [], <>, {} 
                               # with an empty string
                DŠ             # duplicate and move down 2 places on stack
                  Q#           # if the operation didn't alter the list, exit loop
                    ]          # end loop
                     €g        # get the length of each subtring
                       _Ï      # keep only the strings in the original 
                               # list of unique permutations 
                               # that have a length of 0 in the resulting list

Emigna

Posted 2017-04-27T18:13:10.153

Reputation: 50 798

>

  • I think : vectorizes (you can skip most of the infinite loop). 2. It's 1 bytes shorter to use UX at the beginning and X when you need the list of brackets again.
  • < – Riley – 2017-04-28T14:21:30.157

    @Riley: I did try just : first, but we get issues when for example replacements on {} creates possible replacements on () as we've already tried replacing all (). Good point about UX though. We can get another byte with ©® as well. – Emigna – 2017-04-28T14:30:13.957

    The fact that U pops the top was always frustrating. I didn't know about ©®. – Riley – 2017-04-28T14:39:25.057

    I was looking at this answer. Did 05AB1E get an update that broke it, or is that answer not valid?

    – Riley – 2017-04-28T14:40:25.163

    That answer works for [([]{})<{[()<()>]}()>{}], but not for [({})<{[()<()>]}()>{}]. The only difference is the removed []. I'll ask about it in TNB.

    – Riley – 2017-04-28T14:46:15.140

    Why is the output empty? – user202729 – 2018-11-06T14:27:19.707

    @user202729: Some feature of the language has likely changed since this was posted. If you want to run it, I think you'll have to download the version that was live back then. It can probably be made shorter today as well. – Emigna – 2018-11-06T14:36:08.530

    @user202729: this seems to be working with minimal changes. Edit: changed to legacy since it was more efficient for the big test case.

    – Emigna – 2018-11-06T14:39:42.963