module Sol_Exercise_3 where import Test.QuickCheck import Data.List import Data.Char (isSpace) type WrapFun = [Char] -> [Char] type Picture = [[Char]] {- G1 -} snoc :: [a] -> a -> [a] snoc [] y = [y] snoc (x : xs) y = x : snoc xs y member :: Eq a => a -> [a] -> Bool member _ [] = False member e (x : xs) = e == x || member e xs butlast :: [a] -> [a] butlast [] = [] butlast [_] = [] butlast (x : xs) = x : butlast xs {- G2 -} uniq :: Eq a => [a] -> [a] uniq (x:y:ys) = if x == y then uniq (y:ys) else x : uniq (y:ys) uniq xs = xs -- Alternativ: uniq' :: Eq a => [a] -> [a] uniq' [] = [] uniq' (x:xs) = f x xs where f x [] = [x] f x (y:ys) | x == y = f x ys | otherwise = x : f y ys uniqCount :: Eq a => [a] -> [(a, Integer)] uniqCount [] = [] uniqCount (x:xs) = f (x,1) xs where f p [] = [p] f (x,c) (y:ys) | x == y = f (x, c + 1) ys | otherwise = (x,c) : f (y, 1) ys {- G3 -} intersep :: a -> [a] -> [a] intersep sep (c : c' : cs) = c : sep : intersep sep (c' : cs) intersep _ cs = cs andList :: [[Char]] -> [Char] andList [] = "" andList [w] = w andList [w1, w2] = w1 ++ " and " ++ w2 andList [w1, w2, w3] = w1 ++ ", " ++ w2 ++ ", and " ++ w3 andList (w : ws) = w ++ ", " ++ andList ws {- G4 -} triangle :: [a] -> [(a, a)] triangle [] = [] triangle (x : xs) = [(x, x') | x' <- xs] ++ triangle xs {- QuickCheck properties -} prop_triangle_base = triangle ([] :: [Int]) == [] prop_triangle_one x = triangle [x] == [] prop_triangle_two x y = triangle [x, y] == [(x, y)] prop_triangle_length xs = length (triangle xs) == n * (n - 1) `div` 2 where n = length xs prop_triangle_distinct xs = distinct xs ==> distinct (triangle xs) where distinct ys = nub ys == ys prop_triangle_complete x xs y ys = (x, y) `elem` triangle (x : xs ++ y : ys) prop_triangle_sound1 x y xs = not ((x, y) `elem` triangle (delete x (nub xs))) && not ((y, x) `elem` triangle (delete x (nub xs))) prop_triangle_rec x xs = triangle (x : xs) == [(x, x') | x' <- xs] ++ triangle xs {- H1 -} simplifySpaces :: [Char] -> [Char] simplifySpaces s = [if isSpace x then ' ' else x | x <- normalize (trimEnd (trimStart s))] where trimStart [] = [] trimStart (x : xs) | isSpace x = trimStart xs | otherwise = x : xs trimEnd xs = reverse (trimStart (reverse xs)) normalize [] = [] normalize (x : y : xs) | isSpace x && isSpace y = normalize (y : xs) normalize (x : xs) = x : normalize xs simplifySpaces' = concat . intersperse " " . words {- H2 -} prop_wrap1 :: WrapFun -> [Char] -> Bool prop_wrap1 wrap xs = words xs == words (wrap xs) prop_wrap2 :: WrapFun -> [Char] -> Bool prop_wrap2 wrap xs = goodSpaces (wrap xs) where goodSpaces [] = True goodSpaces (x:xs) = (x == ' ' || x == '\n' || not (isSpace x)) && goodSpaces xs -- alternative definition prop_wrap2' wrap xs = all (\x -> x == ' ' || x == '\n' || not (isSpace x)) $ wrap xs prop_wrap3 :: WrapFun -> [Char] -> Bool prop_wrap3 wrap xs = trimmed (wrap xs) where trimmed [] = True trimmed ys = not (isSpace (head ys)) && not (isSpace (last ys)) prop_wrap4 :: WrapFun -> [Char] -> Bool prop_wrap4 wrap xs = not (consecSpace False (wrap xs)) where consecSpace _ [] = False consecSpace False (x : xs) = consecSpace (isSpace x) xs consecSpace True (x : xs) = if isSpace x then True else consecSpace False xs width = 40 prop_wrap5 :: WrapFun -> [Char] -> Bool prop_wrap5 wrap xs = checkLength (lines (wrap xs)) where checkLength [] = True checkLength (x:xs) = (length (words x) == 1 || length x <= width) && checkLength xs -- alternative definition prop_wrap5' wrap xs = all (\x -> length (words x) == 1 || length x <= width) . lines $ wrap xs prop_wrap6 :: WrapFun -> [Char] -> Bool prop_wrap6 wrap xs = True prop_wrap7 :: WrapFun -> [Char] -> Bool prop_wrap7 wrap xs = True prop_wrap8 :: WrapFun -> [Char] -> Bool prop_wrap8 wrap xs = True prop_wrap9 :: WrapFun -> [Char] -> Bool prop_wrap9 wrap xs = True prop_wrap10 :: WrapFun -> [Char] -> Bool prop_wrap10 wrap xs = True {- H3 -} rotateClockwise :: Picture -> Picture rotateClockwise [] = [] rotateClockwise ([] : xss) = rotateClockwise xss rotateClockwise xss = reverse [safeHead xs | xs <- xss] : rotateClockwise [safeTail xs | xs <- xss] where safeHead xs = if null xs then ' ' else head xs safeTail xs = if null xs then [] else tail xs {- H4 -} sublist :: Eq a => [a] -> [a] -> Bool sublist xs [] = null xs sublist xs (y : ys) = xs == take (length xs) (y : ys) || sublist xs ys subseq :: Eq a => [a] -> [a] -> Bool subseq [] _ = True subseq _ [] = False subseq (x : xs) (y : ys) = subseq (if x == y then xs else x : xs) ys {-WETT-} sublist' :: Eq a => [a] -> [a] -> Bool sublist' xs ys = xs == length xs `take` ys || ys /= [] && xs `sublist'` tail ys subseq' :: Eq a => [a] -> [a] -> Bool subseq' xs ys = null xs || ys /= [] && (if head xs == head ys then tail xs else xs) `subseq'` tail ys {-TTEW-} sublist'' xs = elem xs . concatMap inits . tails