-- HW #1 Suggested solutions

-- #1

-- An O(log n) solution
power :: Int -> Int -> Int
power k n | n < 0 = error "negative argument to power"
	  | n == 0 = 1
          | even n = power (k*k) (n `div` 2)
          | odd n = k * power k (n-1)


-- #2

duplicate :: String -> Int -> String
duplicate s n | n <= 0 = ""
	      | otherwise = s ++ (duplicate s (n-1))

-- a simpler alternative
duplicate' s n = concat (replicate n s)

-- #3
-- a

memberNum :: [Int] -> Int -> Int
memberNum [] _ = 0
memberNum (x:xs) s | x == s = 1 + memberNum xs s
                   | otherwise = memberNum xs s

-- alternatives:

memberNum' l s = length [x | x <- l, x == s]

memberNum'' l s = sum [ if x == s then 1 else 0 | x <- l]

-- b
member :: [Int] -> Int -> Bool
member xs s = memberNum xs s > 0

-- some inferior alternatives:
member' xs s = if memberNum xs s > 0 then True else False

member'' xs s | memberNum xs s > 0 = True
              | otherwise = False
-- c

unique :: [Int] -> [Int]
unique xs = unique' xs
  where 
    unique' [] = [] 
    unique' (z:zs) | memberNum xs z == 1 = z:(unique' zs)
                   | otherwise           = unique' zs

-- an alternative:
unique' :: [Int] -> [Int]
unique' xs = [x | x <- xs, memberNum xs x == 1]


-- #4 (Hudak 2.2)

data Shape = Rectangle Side Side
           | Ellipse Radius Radius
           | RtTriangle Side Side
           | Polygon [Vertex]
     deriving Show
type Radius = Float
type Side   = Float
type Vertex  = (Float,Float)

-- assume figures will live in quadrant 1, with one vertex at the origin

rectangle :: Side -> Side -> Shape
rectangle s1 s2 = Polygon [(0,0),(s1,0),(s1,s2),(0,s2)]

rtTriangle :: Side -> Side -> Shape
rtTriangle s1 s2 = Polygon [(0,0),(s1,0),(0,s2)]

-- #5 (Hudak 2.5)

polyArea :: [Vertex] -> Float 
polyArea vs = abs (f (last vs:vs))
  where f ((x1,y1):(x2,y2):vs) = (x2 - x1) * (y1 + y2) / 2.0 + f ((x2,y2):vs)
        f _ = 0.0         

-- an alternative:
-- polyArea (v:vs) = abs (f (v:(vs ++ [v])))

-- simple example
a1 = polyArea [(0,0),(1,0),(1,1),(0,1)]

-- rotated example
a2 = polyArea [(0,0),(1,1),(0,2),(-1,1)]

-- convex example
a3 = polyArea [(0,0),(0,3),(2,3),(2,2),(1,2),(1,1),(2,1),(2,0)]