tags:

views:

743

answers:

4

I am reading the Algorithm Design Manual Second Edition and this is from an exercise question. Quoting the question

A common problem for compilers and text editors is determining whether the parentheses in a string are balanced and properly nested. For example, the string ((())())() contains properly nested pairs of parentheses, which the strings )()( and ()) do not. Give an algorithm that returns true if a string contains properly nested and balanced parentheses, and false if otherwise. For full credit, identify the position of the first offending parenthesis if the string is not properly nested and balanced.

Question is under stacks,queues and lists category. Here is what I wrote in C#.

const char LeftParenthesis = '(';
const char RightParenthesis = ')';
bool AreParenthesesBalanced(string str, out int errorAt)
{
    var items = new Stack<int>(str.Length);
    errorAt = -1;
    for (int i = 0; i < str.Length; i++)
    {
        char c = str[i];
        if (c == LeftParenthesis)
            items.Push(i);
        else if (c == RightParenthesis)
        {
            if (items.Count == 0)
            {
                errorAt = i + 1;
                return false;
            }
            items.Pop();
        }
    }
    if (items.Count > 0)
    {
        errorAt = items.Peek() + 1;
        return false;
    }
    return true;
}

This works well. But I am not sure that this is the right method to approach this problem. Any better ideas are welcome.

A: 

Yes, stacks are the preferred method for parsing this sort of data.

Charlie Salts
+4  A: 

I think this is the intention, but really you just need to decrement and increment a counter if you are only dealing with parenthesis. If you are dealing with the pairings of square brackets, angle brackets, curly braces or whatever character pairing you'd like to use, you'll need a stack like you have done.

You can also use a list, pulling the head element off and on, but really a stack is probably implemented as a list anyway --at least it is in ocaml.

nlucaroni
Yes. In this case, simple implementation would be to increment and decrement a variable. But the requirement is to use any of the data structures. Thanks for the help.
Appu
A naive counter implementation would check only that the value is zero at the end. To answer this question, you would need to immediately fail if it goes negative and also identify the first excess open if it ends up positive. I don't think this will be any easier than the algorithm shown by Appu. As for data structures, it's going to be a stack, whether it's implemented as a linked list or not. In fact, it would work fine implemented over an array that's as large as the string. Or, in the recursive example, we use the real stack.
Steven Sudit
@Appu: It fails the second part, of identifying the offending parenthesis.
Steven Sudit
@Steven: It finds the first offending parenthesis index and assign to errorAt variable.
Appu
@Steven: The chapter isn't about recursion that's why I didn't bring it up. Also, strings are arrays here, and you get no advantage from recursion since you'd be carrying around a counter to access the string elements.
nlucaroni
@Steven: Why wouldn't you find the offending parenthesis by using a counter? As you iterate over the array you +/-1, and if that is ever negative, you've found the offending parenthesis. The point of using a counter over a stack is that you're holding meaningless characters in a stack, in no way does the stack give you anything with it's existence.
nlucaroni
@ncluaroni: There are two failure modes. The easiest is when you hit an close parenthesis but there is no unaccounted for open parenthesis before it. You can then return the current index as the failure point. The harder one is when you get to the end of the string and have one or more opens without closes. How, without something like a stack, would you determine which open is superfluous?
Steven Sudit
@Appu: Yes, your code does do that. I was saying that the algorithm suggested by nclcaroni, which uses a counter instead of a stack, cannot do so.
Steven Sudit
@ncluaroni: Depending on the language and platform, using the native stack may or may not be faster than using a stack class based on an array and index. It would, however, be more elegant.
Steven Sudit
A: 

As TheVillageIdiot said, it's fine. You could also implement it recursively, which might be more elegant, or might not. Finally, you might want to require that matching parentheses contain something valid between them, so as to allow "(a)" but not "()".

Steven Sudit
This answer has had 2 downvotes with 0 explanations. I sense an imbalance. So if you have a reason for your downvote, I suggest you share it.
Steven Sudit
A: 

Why have a return value and an out parameter that give the same information?

You could return an int: -1 = balanced, otherwise the index of the error.

Bill
I thought about it. But some how I felt this pattern is better suited here. Thanks for the help.
Appu
@Bill: You would want to call the method FindInvalidParenthesis, then. Then it would make sense for it to return -1 on failure, and the index on success. Having said that, this Try* interface, which returns a success flag while passing the actual value as an out parameter is in many ways cleaner.
Steven Sudit
That's a good point, a name-change would be in order under this suggestion. But having to set two values and check two values instead of one to determine the result of the function? I'm afraid I don't see how that is cleaner.
Bill