-- sample solutions for Revision Tutorial 2, 14 Nov 2012 import Char import Test.QuickCheck -- Question 1 -- 1a f1 :: [String] -> String f1 xs = concat [ x | x <- xs, not (null x), isUpper (head x) ] -- 1b g1 :: [String] -> String g1 [] = "" g1 (x:xs) | not (null x) && isUpper (head x) = x ++ g1 xs | otherwise = g1 xs test1 = f1 ["This","Is","not","A","non","Test"] == "ThisIsATest" && f1 ["noThing","beGins","uPPER"] == "" && f1 ["Non-words","like","42","get","Dropped"] == "Non-wordsDropped" && f1 ["An","Empty","Word","","gets","dropped"] == "AnEmptyWord" prop_1 :: [String] -> Bool prop_1 xs = f1 xs == g1 xs -- Question 2 -- 2a isVowel x = x == 'a' || x == 'e' || x == 'i' || x == 'o' || x == 'u' || x == 'A' || x == 'E' || x == 'I' || x == 'O' || x == 'U' f2 :: String -> Bool f2 xs = and [ isUpper x | x <- xs, isVowel x] -- 2b g2 :: String -> Bool g2 [] = True g2 (x:xs) | isVowel x = isUpper x && g2 xs | otherwise = g2 xs -- 2c h2 :: String -> Bool h2 xs = foldr (&&) True (map isUpper (filter isVowel xs)) test2 = f2 "ALL CAPS" == True && f2 "r3cURsI0n" == True && f2 [] == True && f2 "normal text" == False prop_2 :: String -> Bool prop_2 xs = f2 xs == g2 xs && g2 xs == h2 xs -- Question 3 -- 3a isSmallDigit x = digitToInt x >= 5 f3 :: String -> Bool f3 xs = and [ isSmallDigit x | x <- xs, isDigit x] -- 3b g3 :: String -> Bool g3 [] = True g3 (x:xs) | isDigit x = isSmallDigit x && g3 xs | otherwise = g3 xs -- 3c h3 :: String -> Bool h3 xs = foldr (&&) True (map isSmallDigit (filter isDigit xs)) test3 = f3 "normal text" == True && f3 "number 75" == True && f3 "" == True && f3 "17 is a prime" == False prop_3 :: String -> Bool prop_3 xs = f3 xs == g3 xs && g3 xs == h3 xs -- Question 4 isPunctuation x = not (isAlpha x || isDigit x) -- 4a f4 :: String -> Bool f4 xs = and [ x == ' ' | x <- xs, isPunctuation x ] -- 4a, alternative answer f4' :: String -> Bool f4' xs = and [ isAlpha x || isDigit x || x == ' ' | x <- xs ] -- 4b g4 :: String -> Bool g4 [] = True g4 (x:xs) | isPunctuation x = x == ' ' && g4 xs | otherwise = g4 xs -- 4c h4 :: String -> Bool h4 = foldr (&&) True . map (== ' ') . filter isPunctuation test4 = f4 "Just two spaces" == True && f4 "No other punctuation, period." == False && f4 "No exclamations!" == False && f4 "What the @#\$!?" == False && f4 "l3tt3rs and d1g1ts 0k" == True && f4 "NoSpacesAtAllOK" == True && f4 "" == True prop_4 :: String -> Bool prop_4 xs = f4 xs == f4' xs && f4' xs == g4 xs && g4 xs == h4 xs -- Question 5 -- 5a f5 :: String -> Bool f5 xs = and [ even (digitToInt x) | x <- xs, isDigit x ] -- 5b g5 :: String -> Bool g5 [] = True g5 (x:xs) | isDigit x = even (digitToInt x) && g5 xs | otherwise = g5 xs -- 5c h5 :: String -> Bool h5 xs = foldr (&&) True (map even (map digitToInt (filter isDigit xs))) test5 = f5 "246" == True && f5 "2467" == False && f5 "x4y2z" == True && f5 "abc12" == False prop_5 :: String -> Bool prop_5 xs = f5 xs == g5 xs && g5 xs == h5 xs