Checking string has balanced parentheses

后端 未结 18 2359
谎友^
谎友^ 2020-12-01 08:42

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

A common problem for comp

18条回答
  •  隐瞒了意图╮
    2020-12-01 08:45

    C# 7 or so now also has tuples. You don't need the out argument anymore. As many others pointed out, there is no need for a stack or a queue or alike.
    Just a balance counter suffices.

        -- Checks the balance of braces in a string.
        -- Error case 1: More closes than open. We can identify the first culprit by index.
        -- Error case 2: More opens than closes. We return the length of the String, 
        --               indicating that there are closed braces missing.
        -- Good case: As many opens as closes. We return (True,Nothing)
        checkBraces :: String -> (Bool,Maybe Int)
        checkBraces [] = (True,Nothing)
        checkBraces s =
            let (balance,offender) = foldl account (0,-1) $ zip [0..] s in
            if balance == 0 
                then (True,Nothing) 
                else (False,Just $ if -1 == offender then length s else offender)
            where
                account :: (Int,Int) -> (Int, Char) -> (Int,Int)
                account acc@(_,off) _ | off /= -1 = acc     -- Once there was an error we stop looking what happens.
                account acc@(b,off) (i,'(') = (b+1,off)     -- One more open brace.
                account (b,off) (i,')')                     -- One more closed brace.
                        | b <= 0 = (b-1,i)                  -- Ouch. We closed more than we opened!
                        | otherwise = (b-1,off)             -- Okay.
                account acc (i,_) = acc                     -- Some other character (Not in ['(',')'])
    
    
        testCases =
            [ ("",True)
            , ("(",False)
            , (")",False)
            , ("))((",False)
            , ("()()",True)
            , ("(()))",False)
            ]
    
        test = 
            all ((==) True) . fmap testOne $ testCases
            where
                testOne (tc,expected) =
                    let (actual,_) = checkBraces tc in
                    actual == expected
    
    

    Side note: The syntax highlighting for Haskell here needs some improvement, right? :)

提交回复
热议问题