-- Informatics 1 Functional Programming -- Mock exam -- -- Solutions import Data.Char import Test.QuickCheck -- Question 1 -- 1a. isFaceCard :: Char -> Bool isFaceCard x = x == 'A' || x == 'K' || x == 'Q' || x == 'J' isCard :: Char -> Bool isCard x = isFaceCard x || (isDigit x && x /= '1') f :: String -> Bool f str = and [ isFaceCard c | c <- str, isCard c ] test1a = f "ABCDE" == True && f "none here" == True && f "4 Aces" == False && f "01234" == False && f "" == True && f "1 Ace" == True -- 1b. g :: String -> Bool g [] = True g (c:str) | isCard c = isFaceCard c && g str | otherwise = g str test1b = g "ABCDE" == True && g "none here" == True && g "4 Aces" == False && g "01234" == False && g "" == True && g "1 Ace" == True -- 1c. h :: String -> Bool h str = foldr (&&) True (map isFaceCard (filter isCard str)) test1c = h "ABCDE" == True && h "none here" == True && h "4 Aces" == False && h "01234" == False && h "" == True && h "1 Ace" == True prop_fg :: String -> Bool prop_fg str = f str == g str prop_fh :: String -> Bool prop_fh str = f str == h str -- Question 2 -- 2a. t :: [a] -> [a] t xs = concat [ if odd i then [x] else [x,x] | (x,i) <- zip xs [1..] ] test2a = t "abcdefg" == "abbcddeffg" && t [1,2,3,4] == [1,2,2,3,4,4] && t "" == "" -- 2b. u :: [a] -> [a] u [] = [] u [x] = [x] u (x:y:xs) = x : y : y : u xs test2b = u "abcdefg" == "abbcddeffg" && u [1,2,3,4] == [1,2,2,3,4,4] && u "" == "" prop_tu_string :: String -> Bool prop_tu_string str = t str == u str prop_tu_intlist :: [Int] -> Bool prop_tu_intlist xs = t xs == u xs -- Question 3 data Chars = Range Char Char | Union Chars Chars | Complement Chars -- 3a. showChars :: Chars -> String showChars (Range c d) = "[" ++ [c] ++ "-" ++ [d] ++ "]" showChars (Union x y) = "(" ++ showChars x ++ "|" ++ showChars y ++ ")" showChars (Complement x) = "~" ++ showChars x test3a = showChars (Range 'a' 'z') == "[a-z]" && showChars (Range 'A' 'Z') == "[A-Z]" && showChars (Union (Range 'a' 'z') (Range 'A' 'Z')) == "([a-z]|[A-Z])" && showChars (Complement (Union (Range 'a' 'z') (Range 'A' 'Z'))) == "~([a-z]|[A-Z])" -- 3b. inChars :: Chars -> Char -> Bool inChars (Range c d) ch = c <= ch && ch <= d inChars (Union x y) ch = inChars x ch || inChars y ch inChars (Complement x) ch = not (inChars x ch) test3b = inChars (Range 'a' 'z') 'd' == True && inChars (Range 'a' 'z') 'D' == False && inChars (Range 'A' 'Z') 'd' == False && inChars (Range 'A' 'Z') 'D' == True && inChars (Union (Range 'a' 'z') (Range 'A' 'Z')) 'd' == True && inChars (Union (Range 'a' 'z') (Range 'A' 'Z')) 'D' == True && inChars (Union (Range 'a' 'z') (Range 'A' 'Z')) '3' == False && inChars (Complement (Union (Range 'a' 'z') (Range 'A' 'Z'))) 'd' == False && inChars (Complement (Union (Range 'a' 'z') (Range 'A' 'Z'))) 'D' == False && inChars (Complement (Union (Range 'a' 'z') (Range 'A' 'Z'))) '3' == True