How to resolve the algorithm Balanced brackets step by step in the Haskell programming language
How to resolve the algorithm Balanced brackets step by step in the Haskell programming language
Table of Contents
Problem Statement
Task:
Let's start with the solution:
Step by Step solution about How to resolve the algorithm Balanced brackets step by step in the Haskell programming language
This Haskell code provides two main functions:
isMatching
: Determines if a string contains balanced brackets.main
: Generates random strings containing brackets and checks their balance.
isMatching
Function
The isMatching
function takes a string as input and returns a Boolean indicating whether the string contains balanced brackets. It uses an automaton-based approach to check for matching brackets.
The function is defined in terms of a fold over a list of characters, where the accumulator is a string representing the state of the automaton. The state is initially empty.
The automaton transitions are defined as follows:
- When encountering an opening bracket
[
, the string is updated to include the opening bracket. - When encountering a closing bracket
]
, if the string contains an opening bracket, it is removed from the string, indicating matching brackets.
main
Function
The main
function generates 10 random strings using a random number generator. Each string contains a varying number of brackets.
For each generated string, the function checks if it contains balanced brackets using the isMatching
function. If the string is balanced, it prints "Good", otherwise it prints "Bad" and indicates the position of the first imbalance.
pairs
Function
The pairs
function generates pairs of indices to be used in swapping elements of a list. It takes three parameters:
l
: The lower bound of the indices.u
: The upper bound of the indices.r
: A random number generator.
The function uses the random number generator to generate a random index j
between i
and u
, where i
is the current index. It then returns a pair of indices (i, j)
and updates the random number generator.
shuffle
Function
The shuffle
function takes a list and a random number generator as input and returns a random permutation of the list.
It uses a Fisher-Yates shuffle algorithm, which involves generating pairs of indices and swapping the elements at those indices. The function uses the pairs
function to generate the pairs of indices.
bracketProblemIndex
Function
The bracketProblemIndex
function takes a string and returns a Maybe
index representing the first unmatched bracket in the string or Nothing
if the string is balanced.
It uses the nesting
function to calculate the nesting levels of the brackets in the string and then checks if any of the levels are negative, indicating an unmatched opening bracket. If the last level is non-zero, it indicates an unmatched closing bracket.
showProblem
Function
The showProblem
function takes a string as input and prints it along with a status message indicating whether the string contains balanced brackets or not.
It uses the bracketProblemIndex
function to check for balance and prints "Unmatched" if an imbalance is found, otherwise it prints "OK".
Source code in the haskell programming language
isMatching :: String -> Bool
isMatching = null . foldl aut []
where
aut ('[':s) ']' = s
-- aut ('{':s) '}' = s -- automaton could be extended
aut s x = x:s
brackets = filter isMatching
$ [1.. ] >>= (`replicateM` "[]{}")
import Control.Monad
import System.Random
import Text.Printf
import VShuffle
-- Return whether a string contains balanced brackets. Nothing indicates a
-- balanced string, while (Just i) means an imbalance was found at, or just
-- after, the i'th bracket. We assume the string contains only brackets.
isBalanced :: String -> Maybe Int
isBalanced = bal (-1) 0
where
bal :: Int -> Int -> String -> Maybe Int
bal _ 0 [] = Nothing
bal i _ [] = Just i
bal i (-1) _ = Just i
bal i n ('[':bs) = bal (i + 1) (n + 1) bs
bal i n (']':bs) = bal (i + 1) (n - 1) bs
-- Print a string, indicating whether it contains balanced brackets. If not,
-- indicate the bracket at which the imbalance was found.
check :: String -> IO ()
check s = maybe (good s) (bad s) (isBalanced s)
where
good = printf "Good \"%s\"\n"
bad s n = printf "Bad \"%s\"\n%*s^\n" s (n + 6) " "
main :: IO ()
main = do
let bs = cycle "[]"
rs <- replicateM 10 newStdGen
zipWithM_ (\n r -> check $ shuffle (take n bs) r) [0,2 ..] rs
module VShuffle
( shuffle
) where
import Data.List (mapAccumL)
import System.Random
import Control.Monad.ST
import qualified Data.Vector as V
import qualified Data.Vector.Generic.Mutable as M
-- Generate a list of array index pairs, each corresponding to a swap.
pairs
:: (Enum a, Random a, RandomGen g)
=> a -> a -> g -> [(a, a)]
pairs l u r = snd $ mapAccumL step r [l .. pred u]
where
step r i =
let (j, r') = randomR (i, u) r
in (r', (i, j))
-- Return a random permutation of the list. We use the algorithm described in
-- http://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle#The_modern_algorithm.
shuffle
:: (RandomGen g)
=> [a] -> g -> [a]
shuffle xs r =
V.toList . runST $
do v <- V.unsafeThaw $ V.fromList xs
mapM_ (uncurry $ M.swap v) $ pairs 0 (M.length v - 1) r
V.unsafeFreeze v
import Control.Applicative ((<|>))
import Data.List (findIndex, replicate, scanl)
import Data.List.Split (chunksOf)
import System.Random
-------------------- BALANCED BRACKETS -------------------
nesting :: String -> [Int]
nesting = tail . scanl (flip level) 0
where
level '[' = succ
level ']' = pred
level _ = id
bracketProblemIndex :: String -> Maybe Int
bracketProblemIndex s =
findIndex (< 0) depths <|> unClosed
where
depths = nesting s
unClosed
| 0 /= last depths = Just $ pred (length s)
| otherwise = Nothing
--------------------------- TEST -------------------------
main :: IO ()
main = do
let g = mkStdGen 137
mapM_ (putStrLn . showProblem) $
chunksOf
6
(bracket <$> take 60 (randomRs (0, 1) g))
showProblem s =
case bracketProblemIndex s of
Just i -> s <> ": Unmatched\n" <> replicate i ' ' <> "^"
_ -> s <> ": OK\n"
bracket :: Int -> Char
bracket 0 = '['
bracket _ = ']'
You may also check:How to resolve the algorithm Sorting algorithms/Cocktail sort step by step in the NetRexx programming language
You may also check:How to resolve the algorithm Doubly-linked list/Element definition step by step in the Pascal programming language
You may also check:How to resolve the algorithm Modified random distribution step by step in the Mathematica/Wolfram Language programming language
You may also check:How to resolve the algorithm String length step by step in the Perl programming language
You may also check:How to resolve the algorithm Euler's sum of powers conjecture step by step in the Kotlin programming language