{- CSci 555, Fall 2010
   Exam #1, 30 September 2010
   Program revised 10 October 2010
   Made into a Haskell 2010 module: 28 Sep 2014
   H. C. Cunningham

123456789012345678901234567890123456789012345678901234567890123456789012

Note -- give " :set +t " command in ghci to display types

-}

module Exam01_555
where

-- Problem 2, partial

p2g = let  (w:x@(y:z)) = [2,4,6] 
      in "w = "   ++ show w ++ ", x = " ++ show x ++ 
         ", y = " ++ show y ++ ", z = " ++ show z

p2j = let ((w:x):y:z) = ["one", "bites", "the dust"]  
         in "w = "   ++ show w ++ ", x = " ++ show x ++ 
            ", y = " ++ show y ++ ", z = " ++ show z


-- Problem 3
-- give " :type p3a " etc to get types
p3a = head
p3b = (++)
p3c = filter
p3d = (.)
p3e = (flip (:))


-- Problem 4
xsss = [["hugs","and"],["kisses"],["from","Hersheys"]]
p4a  = head xsss
p4b  = foldr (++) [] xsss
p4c  = map (map length) xsss
p4d  = filter (==1) (map length xsss)
p4e  = (head . tail . head . tail . tail) xsss


{- Problem 7. Consider a Haskell function floorList that takes a value
   b from any totally ordered set and a list of values xs from the same
   wset and returns xs except that any value that is less than is 
   replaced by b.

    For example, floorList 5 [1, 2, 6, 7, 3, 9]} yields 
   [5, 5, 6, 7, 5, 9]
-}

-- (a) Give an appropriate polymorphic type signature for this function.
-- (b) Define a version of the function that uses (backward) recursion 
-- directly.

floorlist :: Ord a => a -> [a] -> [a]
floorlist b [] = []
floorlist b (x:xs)
  | b >= x     = b:floorlist b xs
  | otherwise  = x:floorlist b xs

p7b = floorlist 5 [1, 2, 6, 7, 3, 9]  -- [5, 5, 6, 7, 5, 9]


-- (c) Define a version of the function that uses the map function.

floorlist1 :: Ord a => a -> [a] -> [a]
floorlist1 b xs = map (max b) xs

p7c = floorlist1 5 [1, 2, 6, 7, 3, 9]  -- [5, 5, 6, 7, 5, 9]


-- (d) Define a function countFloor b xs that takes a value from any
-- totally ordered set and a list of values xs from that same set and
-- returns the count of the number of values greater than equal to
-- b.  (Hint: Maybe use filter.)

countFloor :: Ord a => a -> [a] -> Int
countFloor b xs = length (filter (>=b) xs)

p7d = countFloor 5 [1, 2, 6, 7, 3, 9]  -- 


{- Problem 8. Give the type signature and defining equations for a
   polymorphic Haskell function applyEach that, given a list of
   functions, applies each function to some given value.

   For example, applyEach [(*3), (+2)] 5 yields [15, 7]
-}

applyEach :: [a->b] -> a -> [b]
applyEach [] x     = []
applyEach (f:fs) x = f x : applyEach fs x

p8 = applyEach [(*3), (+2)] 5   -- [15, 7]


{- Problem 9. Give the type signature and defining equations for a
   Haskell function that takes a nonempty list of integers and returns
   a pair (i.e., a 2-tuple) containing the minimum and maximum values
   of the list.  The solution should use a tail recursive auxiliary
   function with accumulating parameters.
-}

minmax :: [Integer] -> (Integer,Integer)
minmax (x:xs) = mm x x xs
  where mm l h []     = (l,h)
        mm l h (x:xs) = mm (min l x) (max h x) xs

p9 = minmax [1,3,5,0,8,1,1,2,2,3]


{- Problem 10. Define the following set of text-justification
   functions.  You may want to use standard prelude functions like take,
   drop, and length.
-}

-- (a) spaces' n returns a string of length n containing only space
-- characters (i.e., the character ' ').

spaces' :: Int -> String
spaces' n
    | n <= 0    = []
    | otherwise = ' ' : spaces' (n-1)

p10a = length (spaces' 5) == 5


-- (b) left' n xs returns a string of length n in which the string xs
-- begins at the head (i.e., left end).'
-- Examples: left' 3 "ab"   yields "ab "  (ending with one blank)
--           left' 3 "abcd" yields "abc"

left' :: Int -> String -> String
left' n xs
  | n <= 0    = []
  | n <= lxs  = take n xs
  | otherwise = xs ++ spaces' (n-lxs)
  where lxs = length xs

p10b1 = left' 3 "ab"
p10b2 = left' 3 "abcd"
