我编写了以下程序来检查平衡括号的字符串:
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)
以下是一些示例数据:
positives = [
isBalanced "",
isBalanced "()",
isBalanced "[]",
isBalanced "{}",
isBalanced "([]){}[{}]"
]
negatives = [
isBalanced "(",
isBalanced "[",
isBalanced "{",
isBalanced ")",
isBalanced "]",
isBalanced "}",
isBalanced "([)]",
isBalanced "{]",
isBalanced ")("
]
由于这个程序只使用显式递归的最基本构建块,我想知道是否有一个更短,更高级的方法涉及我还不知道的语言设施。
好的,我从几个答案和评论(以及我自己的想法)中提炼出以下解决方案:
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
答案 0 :(得分:17)
作为Henning said,解析器组合器可以为此工作。以下是使用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
答案 1 :(得分:10)
import Data.List (foldl')
isBalanced xs = null $ foldl' op [] xs
where
op ('(':xs) ')' = xs
op ('[':xs) ']' = xs
op ('{':xs) '}' = xs
op xs x = x:xs
折叠构建了一堆先前遇到的字符,在找到它们时剥离掉任何匹配项。如果您最终得到一个空列表,则该字符串是平衡的。
使用左折叠的缺点是必须始终扫描整个字符串。如果在没有匹配的开括号的情况下找到闭合支撑,那么中止失败的操作会很好。这是一个可以做到这一点的版本。
import Control.Monad (foldM)
isBalanced' xs = maybe False null $ foldM op [] xs
where
op ('(':xs) ')' = Just xs
op ('[':xs) ']' = Just xs
op ('{':xs) '}' = Just xs
op xs x | x `elem` ")]}" = Nothing
| otherwise = Just (x:xs)
答案 2 :(得分:2)
这个问题可能有点过分,但您可以尝试查找parser combinators。
作为一个更简单的简化,你可以将你的递归重写为折叠一个函数,该函数将一个堆栈和一个字符从字符串转移到一个新的堆栈。 (不过,这实际上是否会更容易实现它在旁观者的眼中)。
答案 3 :(得分:2)
我认为hammar的答案是最好的,但是您可以采取较小的步骤 - 使用null
和lookup
:
{-# LANGUAGE PatternGuards #-}
isBalanced xs = isBalanced' xs []
isBalanced' [] x = null x
isBalanced' (c:xs) ys | Just d <- lookup c par = isBalanced' xs (d:ys)
where par = [('(',')'), ('[',']'),('{','}')]
isBalanced' _ [] = False
isBalanced' (x:xs) (y:ys) = x == y && isBalanced' xs ysl
您的示例positives
和negatives
数据肯定会使用map
,甚至是all
。