Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Checking if a string consists of balanced parenthesis

I wrote the following program to check strings for balanced parenthesis:

isBalanced xs = isBalanced' xs []

isBalanced' [] [] = True
isBalanced' [] _  = False

isBalanced' ('(':xs) ys = isBalanced' xs (')':ys)
isBalanced' ('[':xs) ys = isBalanced' xs (']':ys)
isBalanced' ('{':xs) ys = isBalanced' xs ('}':ys)

isBalanced' _  [] = False

isBalanced' (x:xs) (y:ys) = (x == y) && (isBalanced' xs ys)

Here is some example data:

positives = [
    isBalanced "",
    isBalanced "()",
    isBalanced "[]",
    isBalanced "{}",
    isBalanced "([]){}[{}]"
    ]

negatives = [
    isBalanced "(",
    isBalanced "[",
    isBalanced "{",
    isBalanced ")",
    isBalanced "]",
    isBalanced "}",
    isBalanced "([)]",
    isBalanced "{]",
    isBalanced ")("
    ]

Since this program uses only the most basic building blocks of explicit recursion, I wondered if there was a shorter, more high-level approach involving language facilities I am not yet aware of.


Okay, I distilled the following solution from several answers and comments (and my own thoughts):

import Text.Parsec

grammar = many parens >> return () where
 parens = choice [ between (char opening) (char closing) grammar
                 | [opening, closing] <- ["()", "[]", "{}"]]

isBalanced = isRight . parse (grammar >> eof) ""

isRight (Right _) = True
isRight _         = False
like image 801
fredoverflow Avatar asked Aug 26 '11 18:08

fredoverflow


1 Answers

As Henning said, parser combinators would work for this. Here's an example using Parsec:

import Text.Parsec

grammar = many braces >> return ()
    where braces = choice [ between (char '(') (char ')') grammar
                          , between (char '[') (char ']') grammar
                          , between (char '{') (char '}') grammar
                          ]

isBalanced :: String -> Bool
isBalanced input = case parse (grammar >> eof) "" input of
                       Left  _ -> False
                       Right _ -> True
like image 159
hammar Avatar answered Oct 11 '22 20:10

hammar