CMSI 386
Homework #5
Partial Answers
Warmup.hs
module Warmup
    ( change
    , stripQuotes
    , firstUppercasedOverLengthFive
    , powers
    , sumOfCubesOfOdds
    , swapAdjacents
    , Shape (Box, Sphere)
    , volume
    , surfaceArea
    ) where

import Data.List
import Data.Char

change :: Int -> Either String (Int, Int, Int, Int)
change amount
    | amount < 0 = Left "amount cannot be negative"
    | otherwise =
        let
            (quarters, afterQuarters) = amount`divMod` 25
            (dimes, afterDimes) = afterQuarters `divMod` 10
            (nickels, pennies) = afterDimes `divMod`  5
        in
            Right (quarters, dimes, nickels, pennies)

stripQuotes :: String -> String
stripQuotes = filter (\c -> c /= '\'' && c /= '"')

-- This is a direct approach without any fancy monadic stuff
firstUppercasedOverLengthFive :: [String] -> Maybe String
firstUppercasedOverLengthFive ss = case find ((>5) . length) ss of
    Just s -> Just (map toUpper s)
    Nothing -> Nothing

powers :: Num a => a -> [a]
powers base = map (base^) [0..]

-- The approach with comprehensions
--     powers base = [base ^ i | i <- [0..]]
-- is not as good, IMHO, because the i feels redundant

sumOfCubesOfOdds :: Integral a => [a] -> a
sumOfCubesOfOdds numbers = sum [x ^ 3 | x <- numbers, (not . even) x]

-- I don't mind the comprehensions here. Map and filter is ALSO great:
-- sumOfCubesOfOdds xs = sum $ map (^3) $ filter (not . even) xs

swapAdjacents :: [a] -> [a]
swapAdjacents (x:y:xs) = y:x:swapAdjacents xs
swapAdjacents (x:xs) = [x]
swapAdjacents [] = []

data Shape
    = Sphere Double
    | Box Double Double Double
    deriving (Eq, Show)

volume :: Shape -> Double
volume (Sphere r) = (4 / 3) * pi * (r ^ 3)
volume (Box w l d) = w * l * d

surfaceArea :: Shape -> Double
surfaceArea (Sphere r) = 4 * pi * (r ^ 2)
surfaceArea (Box w l d) = 2 * ((w * l) + (w * d) + (l * d))