-- Solutions to class exam -- 1. type Item = String type Quantity = Int type Price = Int type Entry = (Item, Quantity, Price) -- 1a. important :: Entry -> Bool important (i, q, p) = q > 100 || p > 1000 || q*p > 50000 -- 1b. showEntry :: Entry -> String showEntry (i, q, p) = i ++ star ++ ": " ++ show q ++ "@" ++ showPrice p where star = if important (i,q,p) then "(*)" else "" showPrice p | n == 1 = "0.0" ++ s | n == 2 = "0." ++ s | n >= 3 = take (n-2) s ++ "." ++ drop (n-2) s where s = show p n = length s x1b = showEntry ("Paper clip", 5000, 10) == "Paper clip(*): 5000@0.10" && showEntry ("Notebook", 3, 900) == "Notebook: 3@9.00" -- 1c. showEntries :: [Entry] -> String showEntries es = unlines [ showEntry e | e <- es ] x1c = showEntries [("Paper clip", 5000, 10), ("Notebook", 3, 900)] == "Paper clip(*): 5000@0.10\nNotebook: 3@9.00\n" -- 2. type Pounds = Float -- 2a. lo = 2010 hi = 31400 tax :: Pounds -> Pounds tax x | 0 <= x && x <= lo = 0.10*x | lo < x && x <= hi = 0.22*(x-lo) + tax lo | hi < x = 0.40*(x-hi) + tax hi x2a = tax 20000 == 4158.80 && tax 40000 == 10106.80 -- alternative solution tax' :: Pounds -> Pounds tax' x = 0.10*(0 `max` x `min` lo) + 0.22*((lo `max` x `min` hi) - lo) + 0.40*((hi `max` x) - hi) x2a' = tax' 20000 == 4158.80 && tax' 40000 == 10106.80 -- 2b. highTax :: [Pounds] -> Pounds highTax xs = sum [ tax x | x <- xs, x >= hi ] x2b = highTax [40000, 20000, 40000] == 20213.60 -- 2c. highTax' :: [Pounds] -> Pounds highTax' [] = 0 highTax' (x:xs) | x >= hi = tax x + highTax' xs | otherwise = highTax' xs x2c = highTax' [40000, 20000, 40000] == 20213.60 -- 3. -- 3a. nextRow :: [Int] -> [Int] nextRow xs = [ x+y | (x,y) <- zip ([0]++xs) (xs++[0]) ] x3a = nextRow [1,3,3,1] == [1,4,6,4,1] -- alternative solution nextRow' :: [Int] -> [Int] nextRow' xs = zipWith (+) ([0]++xs) (xs++[0]) x3a' = nextRow' [1,3,3,1] == [1,4,6,4,1] -- alternative solution nextRow'' :: [Int] -> [Int] nextRow'' xs = adjacentsum ([0]++xs++[0]) where adjacentsum [0] = [] adjacentsum (x:y:ys) = x+y : adjacentsum (y:ys) x3a'' = nextRow'' [1,3,3,1] == [1,4,6,4,1] -- 3b. pascal :: Int -> [[Int]] pascal n = loop n [1] where loop 1 xs = [xs] loop n xs | n > 1 = xs : loop (n-1) (nextRow xs) x3b = pascal 6 == [[1],[1,1],[1,2,1],[1,3,3,1],[1,4,6,4,1],[1,5,10,10,5,1]] -- alternative solution pascal' :: Int -> [[Int]] pascal' n = take n (iterate nextRow [1]) x3b' = pascal 6 == [[1],[1,1],[1,2,1],[1,3,3,1],[1,4,6,4,1],[1,5,10,10,5,1]] -- 1c. centre :: Int -> String -> String centre w s | n <= w = replicate h ' ' ++ s where n = length s h = (w - n) `div` 2 showLine :: Int -> [Int] -> String showLine w xs = centre w (unwords [ show x | x <- xs ]) x3c = showLine 20 [1,4,6,4,1] == " 1 4 6 4 1" -- 1d. showPascal :: Int -> Int -> String showPascal w n = unlines [ showLine w xs | xs <- pascal n ] x3d = showPascal 20 6 == " 1\n" ++ " 1 1\n" ++ " 1 2 1\n" ++ " 1 3 3 1\n" ++ " 1 4 6 4 1\n" ++ " 1 5 10 10 5 1\n"