-- This are my solutions to the exercises from https://github.com/moocfi/haskell-mooc import Data.List import Data.Char import Data.Either --------- -- Set.01 -- https://github.com/moocfi/haskell-mooc/blob/master/exercises/Set1.hs -- Ex. 1 one :: Integer -- function declaration: types of arguments and output one = 1 -- function definition two :: Integer two = 2 -- Ex. 2 double :: Integer -> Integer double x = x * 2 -- Ex. 3 quadruple :: Integer -> Integer quadruple x = double (double x) -- Ex. 4 distance :: Double -> Double -> Double -> Double -> Double -- exponentiation operator: ^ for integers, ^^ for fractionals and ** for floating point distance x1 y1 x2 y2 = sqrt (abs(x1 - x2)**2 + abs(y1 - y2)**2) -- Ex. 5 eeny :: Integer -> String eeny x = if even x then "eeny" else "meeny" -- Ex. 6 checkPassword :: String -> String checkPassword password = if password == "swordfish" || password == "mellon" then "You're in." else "ACCESS DENIED!" -- Ex. 7 postagePrice :: Int -> Int postagePrice weight = if weight > 5000 then 6000 else if weight > 500 then 300 + weight * 1 else 250 -- Ex. 8 isZero :: Int -> Bool isZero 0 = True -- this is pattern matching isZero x = False -- Ex. 9 sumTo :: Int -> Int sumTo 1 = 1 sumTo n = n + sumTo (n - 1) -- Ex. 10 power :: Int -> Int -> Int power n 1 = n power n k = n * power n (k - 1) -- Ex. 11 ilog3 :: Int -> Int ilog3 0 = 0 ilog3 n = 1 + ilog3 (div n 3) ---------- -- Set.02a -- https://github.com/moocfi/haskell-mooc/blob/master/exercises/Set2a.hs -- Functions you'll need: head, tail, take, drop, length, null -- Can only use Data.List -- Ex. 1 years = [1982, 2004, 2020] -- Ex. 2 takeFinal :: Int -> [a] -> [a] -- a is the Haskell equivalent of generics (T) in C# takeFinal n xs | n > length xs = xs | otherwise = drop (length xs - n) xs -- Ex. 3 updateAt :: Int -> a -> [a] -> [a] -- elements before i + x + elemenets after i ; ++ concatenates arrays updateAt i x xs = take i xs ++ [x] ++ drop (i + 1) xs -- Ex. 4 substring :: Int -> Int -> String -> String substring i j s = drop i (take j s) -- Ex. 5 isPalindrome :: String -> Bool isPalindrome s = s == reverse s -- Ex. 6 palindromify :: String -> String palindromify s = if isPalindrome s then s -- can easily make it: if s == reverse s then s , but decided this way was more readable else palindromify (take (length s - 2) (drop 1 s)) -- Ex. 7 safeDiv :: Int -> Int -> String safeDiv x y | y == 0 = "Nothing" | otherwise = "Just " ++ show (div x y) -- show casts the value to string -- Ex. 8 greet :: String -> Maybe String -> String -- maybe means the value can (String) or can not be given (Nothing) ; you need to use pattern matching greet firstName Nothing = "Hello, " ++ firstName ++ "!" greet firstName (Just lastName) = "Hello, " ++ firstName ++ " " ++ lastName ++ "!" -- Ex. 9 safeIndex :: [a] -> Int -> Maybe a safeIndex xs i = if 0 > i || i >= length xs then Nothing else Just (xs !! i) -- Ex. 10 eitherDiv :: Int -> Int -> Either String Int -- a value type can be the left one or the right one (specified when given) eitherDiv x 0 = Left (show x ++ "/0") eitherDiv x y = Right (div x y) -- Ex. 11 addEithers :: Either String Int -> Either String Int -> Either String Int addEithers (Right x) (Right y) = Right (x + y) addEithers (Right x) (Left y) = Left y addEithers (Left x) (Right y) = Left x ---------- -- Set.02b -- https://github.com/moocfi/haskell-mooc/blob/master/exercises/Set2b.hs -- Ex. 1 binomial :: Int -> Int -> Int binomial n 0 = 1 binomial 0 k | k > 0 = 0 | otherwise = (-1) binomial n k = binomial (n - 1) k + binomial (n - 1) (k - 1) -- Ex. 2 oddFactorial :: Int -> Int oddFactorial 1 = 1 -- technically having a pattern match for 3 is more efficient oddFactorial n |even n = oddFactorial (n - 1) |otherwise = n * oddFactorial (n - 2) -- Ex. 3 myGcd :: Int -> Int -> Int myGcd 0 b = b myGcd a 0 = a myGcd a b | a > b = myGcd (a - b) b | otherwise = myGcd a (b - a) -- Ex. 4 leftpad :: String -> Int -> String leftpad s a = if length s >= a then s else leftpad (" " ++ s) a -- Ex. 5 countdown :: Int -> String countdown n = "Ready! " ++ count n ++ "Liftoff!" count :: Int -> String -- recursive helper function count 0 = "" count n = show n ++ "... " ++ count (n - 1) -- Ex. 6 smallestDivisor :: Int -> Int smallestDivisor n = smallest n 2 smallest :: Int -> Int -> Int smallest n k = if mod n k == 0 then k else smallest n (k + 1) -- Ex. 7 isPrime :: Int -> Bool isPrime 1 = False isPrime n = smallestDivisor n == n -- Ex. 8 biggestPrimeAtMost :: Int -> Int biggestPrimeAtMost n = if isPrime n then n else biggestPrimeAtMost (n - 1) ---------- -- Set.03a -- https://github.com/moocfi/haskell-mooc/blob/master/exercises/Set3a.hs -- Can only use Data.List, Data.Either, Data.Char -- Ex. 1 maxBy :: (a -> Int) -> a -> a -> a maxBy measure a b = if (measure a) > (measure b) then a else b -- Ex. 2 mapMaybe :: (a -> b) -> Maybe a -> Maybe b mapMaybe f Nothing = Nothing mapMaybe f (Just a) = Just (f a) -- Ex. 3 mapMaybe2 :: (a -> b -> c) -> Maybe a -> Maybe b -> Maybe c mapMaybe2 f (Just a) Nothing = Nothing mapMaybe2 f Nothing (Just b) = Nothing mapMaybe2 f (Just a) (Just b) = Just (f a b) -- Ex. 4 palindromeHalfs :: [String] -> [String] palindromeHalfs xs = map firstHalf (filter palindrome xs) firstHalf :: String -> String -- div rounds down to negative infinity, meaning 2.5 will be rounded down to 2 and -2.5 to -3 -- using this feature, we can round up a division of integers by one of them being negative and taking the absolute result firstHalf s = take (abs (div (length s) (-2))) s palindrome :: String -> Bool palindrome s = s == reverse s -- Ex. 5 capitalize :: String -> String capitalize s = unwords (map capitlizeFirst (words s)) where capitlizeFirst s = [toUpper (head s)] ++ tail s -- helper function, only available in capitalize -- Ex. 6 powers :: Int -> Int -> [Int] powers k max = filter (<=max) (map (\x -> k ^ x) [0..max]) -- Ex. 7 while :: (a -> Bool) -> (a -> a) -> a -> a while check update value = if check value then while check update (update value) else value -- Ex. 8 whileRight :: (a -> Either b a) -> a -> b whileRight f x = either (\y -> y) (\y -> whileRight f y) (f x) step :: Int -> Int -> Either Int Int -- function for testing step k x = if x < k then Right (2*x) else Left x -- Ex. 9