diff --git a/Exercises/exercise-3/Regex.hs b/Exercises/exercise-3/Regex.hs index 98cd08a..d79deb3 100644 --- a/Exercises/exercise-3/Regex.hs +++ b/Exercises/exercise-3/Regex.hs @@ -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 \ No newline at end of file +shouldBeFalse4 :: Bool +shouldBeFalse4 = match r4 "abbabc" +-- >>> match r4 "abbabc" +-- False +--