Solve Regex task

This commit is contained in:
Manuel Thalmann 2024-06-15 22:59:46 +02:00
parent d6029978c7
commit 7b4b2593ac

View file

@ -7,6 +7,9 @@ data Regex
= Empty
| Epsilon
| Symbol Char
| Sequence Regex Regex
| Star Regex
| Choice Regex Regex
-- | Sequence, Star, Choice fehlen noch.
deriving Show
@ -26,7 +29,13 @@ data Regex
tails (\s -> length s >= 1) "abcde" == ["bcde","cde","de","e",""]
-}
tails :: (String -> Bool) -> String -> [String]
tails f s = error "fixme"
tails f s = concatMap
(\x -> if f (take x s) then [(drop x s)] else [])
[0..(length s)]
-- >>> tails (\s -> length s >= 1) "abcde"
-- ["bcde","cde","de","e",""]
--
{- Helper function 2:
By repeatedly calling the tails function, this function checks if
@ -41,7 +50,16 @@ segmentable f s
| s == "" = True
| "" `elem` leads = True
| leads == [] = False
| otherwise = error "fixme"
| otherwise = or (map (\x -> segmentable f x) leads)
where
leads = tails f s
-- >>> segmentable (\s -> length s == 2) "abcde"
-- False
--
-- >>> segmentable (\s -> length s == 2) "abcd"
-- True
--
{- Helper function 3:
Given two predicates and a string, this function checks if it is
@ -54,7 +72,22 @@ segmentable f s
combinable (\s -> length s == 2) (\s -> length s == 3) "123456" == False
-}
combinable :: (String -> Bool) -> (String -> Bool) -> String -> Bool
combinable f g s = error "fixme"
combinable f g s =
or (
map
(\x -> f (take x s) && g (drop x s))
(reverse [0..len])
)
where
len = length s
-- >>> combinable (\s -> length s == 2) (\s -> length s == 3) "12345"
-- >>> combinable (\s -> length s == 2) (\s -> length s == 3) "1234"
-- >>> combinable (\s -> length s == 2) (\s -> length s == 3) "123456"
-- True
-- False
-- False
--
{-
Matching a particular string to a regex a regex now simply means to check
@ -62,12 +95,12 @@ combinable f g s = error "fixme"
-}
match :: Regex -> String -> Bool
match r s = case r of
Empty -> error "fixme"
Epsilon -> error "fixme"
Symbol c -> error "fixme"
Choice r1 r2 -> error "fixme"
Sequence r1 r2 -> error "fixme"
Star r1 -> error "fixme"
Empty -> s == ""
Epsilon -> False
Symbol c -> s == [c]
Choice r1 r2 -> (match r1 s || match r2 s)
Sequence r1 r2 -> combinable (match r1) (match r2) s
Star r1 -> segmentable (match r1) s
{-
Examples/test-cases
-}
@ -101,24 +134,49 @@ r4 = Sequence (Symbol 'a') $ Star $ Choice (Symbol 'a') (Symbol 'b')
shouldBeTrue1 :: Bool
shouldBeTrue1 = match r1 "abbbbaccca"
-- >>> match r1 "abbbbaccca"
-- True
--
shouldBeFalse1 :: Bool
shouldBeFalse1 = match r1 "abbcc"
-- >>> match r1 "abbcc"
-- False
--
shouldBeTrue2 :: Bool
shouldBeTrue2 = match r2 "abbbbacccabxxxx"
-- >>> match r2 "abbbbacccabxxxx"
-- True
--
shouldBeFalse2 :: Bool
shouldBeFalse2 = match r2 "abbxxxacc"
-- >>> match r2 "abbxxxacc"
-- False
--
shouldBeTrue3 :: Bool
shouldBeTrue3 = match r3 "ab"
-- >>> match r3 "ab"
-- True
--
shouldBeFalse3 :: Bool
shouldBeFalse3 = match r3 "aba"
-- >>> match r3 "aba"
-- False
--
shouldBeTrue4 :: Bool
shouldBeTrue4 = match r4 "abbbab"
-- >>> match r4 "abbbab"
-- True
--
shouldBeFalse4 :: Bool
shouldBeFalse4 :: Bool
shouldBeFalse4 = match r4 "abbabc"
-- >>> match r4 "abbabc"
-- False
--