tags:

views:

1278

answers:

14

This came up while talking to a friend and I thought I'd ask here since it's an interesting problem and would like to see other people's solutions.

The task is to write a function Brackets(int n) that prints all combinations of well-formed brackets from 1...n. For Brackets(3) the output would be

()
(())  ()()   
((()))  (()())  (())()  ()(())  ()()()
+5  A: 

F#:

UPDATE: this answer is wrong. My N=4 misses, for example "(())(())". (Do you see why?) I will post a correct (and more efficient) algorithm shortly.

(Shame on all you up-voters, for not catching me! :) )


Inefficient, but short and simple. (Note that it only prints the 'nth' line; call in a loop from 1..n to get the output asked for by the question.)

#light
let rec brackets n =
    if n = 1 then
        ["()"]
    else
        [for s in brackets (n-1) do
            yield "()" ^ s
            yield "(" ^ s ^ ")"
            yield s ^ "()"]

Example:

Set.of_list (brackets 4) |> Set.iter (printfn "%s")
(*
(((())))
((()()))
((())())
((()))()
(()(()))
(()()())
(()())()
(())()()
()((()))
()(()())
()(())()
()()(())
()()()()
*)
Brian
For n=2, doesn't this print ()() twice?
David Zaslavsky
Making it a 'set' guarantees uniqueness.Nevertheless, this answer is wrong! Update forthcoming.
Brian
+7  A: 

F#:

Here is a solution that, unlike my previous solution, I believe may be correct. Also, it is more efficient.

#light

let brackets2 n =
    let result = new System.Collections.Generic.List<_>()
    let a = Array.create (n*2) '_'
    let rec helper l r diff i =
        if l=0 && r=0 then
            result.Add(new string(a))
        else
            if l > 0 then
                a.[i] <- '('
                helper (l-1) r (diff+1) (i+1)
            if diff > 0 then
                a.[i] <- ')'
                helper l (r-1) (diff-1) (i+1)
    helper n n 0 0
    result

Example:

(brackets2 4) |> Seq.iter (printfn "%s")

(*
(((())))
((()()))
((())())
((()))()
(()(()))
(()()())
(()())()
(())(())
(())()()
()((()))
()(()())
()(())()
()()(())
()()()()
*)
Brian
I upvoted, but why not just update your original post?
KingNestor
I think it may be instructive to keep it around; so often people just glance at answers, think they look good, and upvote. It serves as a reminder to be cautious. Feel free to downvote it, as it deserves it.
Brian
Also I like the use of yield in the first post. I hadn't used it before and it's really handy though not in this particular scenario.
aleemb
+5  A: 

The number of possible combinations is the Catalan number of N pairs C(n).

This problem was discussed on the joelonsoftware.com forums pretty exentsively including iterative, recursive and iterative/bitshifting solutions. Some pretty cool stuff there.

Here is a quick recursive solution suggested on the forums in C#:

C#

public void Brackets(int pairs) {
    if (pairs > 1) Brackets(pairs - 1);
 char[] output = new char[2 * pairs];

 output[0] = '(';
 output[1] = ')';

 foo(output, 1, pairs - 1, pairs, pairs);
    Console.writeLine();
}

public void foo(char[] output, int index, int open, int close,
  int pairs) {
 int i;

 if (index == 2 * pairs) {
  for (i = 0; i < 2 * pairs; i++)
   Console.write(output[i]);
  Console.write('\n');
  return;
 }

 if (open != 0) {
  output[index] = '(';
  foo(output, index + 1, open - 1, close, pairs);
 }

 if ((close != 0) && (pairs - close + 1 <= pairs - open)) {
  output[index] = ')';
  foo(output, index + 1, open, close - 1, pairs);
 }

 return;
}

Brackets(3);

Output:
()
(()) ()()
((())) (()()) (())() ()(()) ()()()

KingNestor
as per forum, fourth line should read __output[2*pairs - 1] = ')';__ not __output[1] = ')';__
aleemb
@KingNestor, I made a quick edit to the code so it spits it out exactly as the OP wanted. Small change, I called Brackets() recursively which then called foo() recursively. I'm trying to shrink yours down a little right now.
Simucal
Yes, everyone.. feel free to help reduce this one down further. It would be nice if we could get rid of the intermediary function before the recursive call.
KingNestor
Wow, why the -2 downvotes?
KingNestor
+2  A: 

Damn - everyone beat me to it, but I have a nice working example :)

http://www.fiveminuteargument.com/so-727707

The key is identifying the rules, which are actually quite simple:

  • Build the string char-by-char
  • At a given point in the string
    • if brackets in string so far balance (includes empty str), add an open bracket and recurse
    • if all open brackets have been used, add a close bracket and recurse
    • otherwise, recurse twice, once for each type of bracket
  • Stop when you get to the end :-)
Bobby Jack
+1  A: 

Here is a solution in C++. The main idea that I use is that I take the output from the previous i (where i is the number of bracket pairs), and feed that as input to the next i. Then, for each string in the input, we put a bracket pair at each location in the string. New strings are added to a set in order to eliminate duplicates.

#include <iostream>
#include <set>
using namespace std;
void brackets( int n );
void brackets_aux( int x, const set<string>& input_set, set<string>& output_set );

int main() {
    int n;
    cout << "Enter n: ";
    cin >> n;
    brackets(n);
    return 0;
}

void brackets( int n ) {
    set<string>* set1 = new set<string>;
    set<string>* set2;

    for( int i = 1; i <= n; i++ ) {
        set2 = new set<string>;
        brackets_aux( i, *set1, *set2 );
        delete set1;
        set1 = set2;
    }
}

void brackets_aux( int x, const set<string>& input_set, set<string>& output_set ) {
    // Build set of bracket strings to print
    if( x == 1 ) {
        output_set.insert( "()" );
    }
    else {
        // For each input string, generate the output strings when inserting a bracket pair
        for( set<string>::iterator s = input_set.begin(); s != input_set.end(); s++ ) {
            // For each location in the string, insert bracket pair before location if valid
            for( unsigned int i = 0; i < s->size(); i++ ) {
                string s2 = *s;
                s2.insert( i, "()" );
                output_set.insert( s2 );
            }
            output_set.insert( *s + "()" );
        }
    }

    // Print them
    for( set<string>::iterator i = output_set.begin(); i != output_set.end(); i++ ) {
        cout << *i << "  ";
    }
    cout << endl;
}
MahlerFive
Not recursive but still a cool take on it!
KingNestor
+13  A: 

Took a crack at it.. C# also. I think this is a lot cleaner than the other C# solution above.

    public void Brackets(int n)
    {
        for (int i = 1; i <= n; i++)
        {
            Brackets("", 0, 0, i);
        }
    }
    private void Brackets(string output, int open, int close, int pairs)
    {
        if((open==pairs)&&(close==pairs))
        {
            Console.WriteLine(output);
        }
        else
        {
            if(open<pairs)
                Brackets(output + "(", open+1, close, pairs);
            if(close<open)
                Brackets(output + ")", open, close+1, pairs);
        }
    }

The recursion is taking advantage of the fact that you can never add more opening brackets than the desired number of pairs, and you can never add more closing brackets than opening brackets..

markt
Very, very nice.
kvb
nice indeed! esp leveraging the precondition opening-braces >= closing-braces.
aleemb
@Prabhu Jayaraman - with which input will it produce invalid pairs ? The conditions restrict it to never add a closing bracket if there are not already opening brackets, so I do not think you are correct.
markt
@Prabhu Jayaraman - why ? Please give me an example input that produces incorrect results.
markt
OOps very sorry markt. wrong judgement. i thought `close<pairs` +1
Prabhu Jayaraman
Very elegant solution.. you nailed recursion!
satyajit
+3  A: 

Here's another F# solution, favoring elegance over efficiency, although memoization would probably lead to a relatively well performing variant.

let rec parens = function
| 0 -> [""]
| n -> [for k in 0 .. n-1 do
        for p1 in parens k do
        for p2 in parens (n-k-1) ->
          sprintf "(%s)%s" p1 p2]

Again, this only yields a list of those strings with exactly n pairs of parens (rather than at most n), but it's easy to wrap it.

kvb
Elegant!It may be fun to memoize and then compare the perf for N=12 or so.
Brian
On my machine, a memoized version of this code (slightly modified to replace the sprintf with concatenation) runs in ~.6s for N=12, whereas your code runs in ~.2s. The difference gets worse as you go up from there, though. Some of this is due to string concatenation, which you nicely avoid.
kvb
+2  A: 
def @memo brackets ( n )
    => [] if n == 0 else around( n ) ++ pre( n ) ++ post( n ) ++ [ "()" * n) ]

def @memo pre ( n )
    => map ( ( s ) => "()" ++ s, pre ( n - 1 ) ++ around ( n - 1 ) ) if n > 2 else []

def @memo post ( n )
    => map ( ( s ) => s ++ "()", post ( n - 1 ) ++ around ( n - 1 ) ) if n > 2 else []

def @memo around ( n )
    => map ( ( s ) => "(" ++ s ++ ")", brackets( n - 1 ) )

(kin, which is something like an actor model based linear python with traits. I haven't got round to implementing @memo but the above works without that optimisation)

Pete Kirkham
+2  A: 

A simple F#/OCaml solution :

let total_bracket n =
    let rec aux acc = function
        | 0, 0 -> print_string (acc ^ "\n")
        | 0, n -> aux (acc ^ ")") (0, n-1)
        | n, 0 -> aux (acc ^ "(") (n-1, 1)
        | n, c ->
                aux (acc ^ "(") (n-1, c+1);
                aux (acc ^ ")") (n,   c-1)
    in
    aux "" (n, 0)

Raoul Supercopter
+3  A: 

Common Lisp:

This doesn't print them, but does produce a list of lists of all the possible structures. My method is a bit different from the others'. It restructures the solutions to brackets(n - 1) such that they become brackets(n). My solution isn't tail recursive, but it could be made so with a little work.

Code

(defun brackets (n)
  (if (= 1 n)
      '((()))
      (loop for el in (brackets (1- n))
            when (cdr el)
            collect (cons (list (car el)) (cdr el))
            collect (list el)
            collect (cons '() el))))
Sebastian Krog
A: 

Not the most elegant solution, but this was how I did it in C++ (Visual Studio 2008). Leveraging the STL set to eliminate duplicates, I just naively insert new () pairs into each string index in every string from the previous generation, then recurse.

#include "stdafx.h"
#include <iostream>
#include <string>
#include <set>

using namespace System;
using namespace std;

typedef set<string> StrSet;

void ExpandSet( StrSet &Results, int Curr, int Max )
{
    if (Curr < Max)
    {
        StrSet NewResults;

        for (StrSet::iterator it = Results.begin(); it != Results.end(); ++it)
        {
            for (unsigned int stri=0; stri < (*it).length(); stri++)
            {
                string NewStr( *it );
                NewResults.insert( NewStr.insert( stri, string("()") ) );
            }
        }
        ExpandSet( NewResults, Curr+1, Max );

        Results = NewResults;
    }
}    

int main(array<System::String ^> ^args)
{
    int ParenCount = 0;

    cout << "Enter the parens to balance:" << endl;
    cin  >> ParenCount;

    StrSet Results;
    Results.insert( string("()") );

    ExpandSet(Results, 1, ParenCount);

    cout << Results.size() << ": Total # of results for " << ParenCount << " parens:" << endl;

    for (StrSet::iterator it = Results.begin(); it != Results.end(); ++it)
    {
        cout << *it << endl;
    }


    return 0;
}
Jason
+1  A: 

Simple solution in C++:

#include <iostream>
#include <string>

void brackets(string output, int open, int close, int pairs)
{
    if(open == pairs && close == pairs)
            cout << output << endl;
    else
    {
            if(open<pairs)
                    brackets(output+"(",open+1,close,pairs);
            if(close<open)
                    brackets(output+")",open,close+1,pairs);
    }
}

int main()
{
    for(int i=1;i<=3;i++)
    {
            cout << "Combination for i = " << i << endl;
            brackets("",0,0,i);
    }
}

Output:

Combination for i = 1
()
Combination for i = 2
(())
()()
Combination for i = 3
((()))
(()())
(())()
()(())
()()()
Prabhu Jayaraman
+1  A: 

Haskell:

I tried to come up with an elegant list monad-y way to this:

import Control.Applicative

brackets :: Int -> [String]
brackets n = f 0 0 where
    f pos depth =
        if pos < 2*n
            then open <|> close
            else stop where
                -- Add an open bracket if we can
                open =
                    if depth < 2*n - pos
                        then ('(' :) <$> f (pos+1) (depth+1)
                        else empty

                -- Add a closing bracket if we can
                close = 
                    if depth > 0
                        then (')' :) <$> f (pos+1) (depth-1)
                        else empty

                -- Stop adding text.  We have 2*n characters now.
                stop = pure ""

main = readLn >>= putStr . unlines . brackets
Joey Adams
A: 

why cant this is as simple as this, this idea is quite simple

brackets(n) --> '()' + brackets(n-1) 0 '(' + brackets(n-1) + ')' 0 brackets(n-1) + '()'

where 0 is the concatenation operation above

public static Set<String> brackets(int n) {
    if(n == 1){
        Set<String> s = new HashSet<String>();
        s.add("()");
        return s;
    }else{
        Set<String> s1 = new HashSet<String>();
        Set<String> s2 = brackets(n - 1);
        for(Iterator<String> it = s2.iterator(); it.hasNext();){
            String s = it.next();
            s1.add("()" + s);
            s1.add("(" + s + ")");
            s1.add(s + "()");
        }
        s2.clear();
        s2 = null;
        return s1;
    }
}
Naresh

related questions