module Exercise_3_Sol where import Test.QuickCheck import Data.List {- Library DO NOT CHANGE -} type Picture = [[Char]] type PadNumbersFn = [Integer] -> [String] printPicture :: Picture -> IO () printPicture [] = return () printPicture (xs : xss) = do putStrLn xs printPicture xss pic = [".##.", ".#.#", ".###", "####"] export_prop_padNumbers :: PadNumbersFn -> [Integer] -> Property export_prop_padNumbers f xs = property $ prop_padNumbers f xs {- End Library -} {-G3.1-} 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 {-G3.2-} 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.3-} 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 {-G3.4-} 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 {-H3.1-} allSameLength :: [[a]] -> Bool allSameLength [] = True allSameLength (xs:xss) = and [length xs' == l | xs' <- xss] where l = length xs prop_padNumbers f xs = length ys == length xs && allSameLength [y | y <- ys] && and [unpad y == show x | (x, y) <- zip xs ys] where ys = f xs unpad (' ':xs) = unpad xs unpad ('-':' ':xs) = '-' : unpad xs unpad xs = xs padNumbers :: [Integer] -> [String] padNumbers xs = [pad x | x <- xs] where maxLength = maximum [length (show x) | x <- xs] pad' prefix str = prefix ++ replicate (maxLength - length str - length prefix) ' ' ++ str pad x = pad' (if x < 0 then "-" else "") (show (abs x)) {-H3.2-} wrapText :: Integer -> [String] -> String wrapText = wrapText2 -- verwendete Funktionen: -- 'genericLength' ist eine Variante von 'length', die statt 'Int' einen 'Integer' zurückliefert -- 'unwords' :: [String] -> String konkateniert eine String-Liste und fügt Leerzeichen zwischen -- die einzelnen Wörter ein wrapText1 :: Integer -> [String] -> String wrapText1 n = f (0,[]) where f (_,[]) (w : ws) = f (genericLength w, [w]) ws f (m,l) (w : ws) | m' <= n = f (m', (w : l)) ws | otherwise = unwords (reverse l) ++ "\n" ++ f (0,[]) (w : ws) where m' = m + 1 + genericLength w f (_,l) [] = unwords (reverse l) -- Alternativ: wrapText2 :: Integer -> [String] -> String wrapText2 n = f True n where f True m (w:ws) = w ++ f False (m - genericLength w) ws f False m (w:ws) | m' >= 0 = " " ++ w ++ f False m' ws | otherwise = "\n" ++ f True n (w:ws) where m' = m - genericLength w - 1 f _ m [] = "" {-H3.3-} stretch :: Picture -> Picture stretch lines = duplicate [ duplicate line | line <- lines ] where duplicate [] = [] duplicate (x:xs) = x : x : duplicate xs {-H3.4-} coalesce :: [(String, Integer)] -> [(String, Integer)] coalesce [] = [] coalesce ((k1, v1) : (k2, v2) : xs) | k1 == k2 = coalesce ((k1, v1 + v2) : xs) coalesce (x : xs) = x : coalesce xs