mirror of
https://github.com/iritmaximus/haskell.git
synced 2026-10-12 19:13:39 +03:00
184 lines
5.7 KiB
Haskell
184 lines
5.7 KiB
Haskell
-- Exercise set 2:
|
|
-- * Guards
|
|
-- * Lists
|
|
-- * Maybe
|
|
-- * Either
|
|
--
|
|
-- Functions you will need:
|
|
-- * head, tail
|
|
-- * take, drop
|
|
-- * length
|
|
-- * null
|
|
|
|
module Set2a where
|
|
|
|
import Mooc.Todo
|
|
|
|
-- Some imports you'll need. Don't add other imports :)
|
|
import Data.List
|
|
|
|
------------------------------------------------------------------------------
|
|
-- Ex 1: Define the constant years, that is a list of the values 1982,
|
|
-- 2004 and 2020 in this order.
|
|
|
|
years :: [Int]
|
|
years = [1982, 2004, 2020]
|
|
|
|
------------------------------------------------------------------------------
|
|
-- Ex 2: define the function takeFinal, which returns the n last
|
|
-- elements of the given list.
|
|
--
|
|
-- If the list is shorter than n, return all elements.
|
|
--
|
|
-- Hint! remember the take and drop functions.
|
|
-- 3
|
|
-- [12345]
|
|
-- ^^^
|
|
|
|
takeFinal :: Int -> [a] -> [a]
|
|
takeFinal n xs
|
|
| n >= length xs = xs
|
|
| otherwise = drop (length xs - n) xs
|
|
|
|
------------------------------------------------------------------------------
|
|
-- Ex 3: Update an element at a certain index in a list. More
|
|
-- precisely, return a list that is identical to the given list except
|
|
-- the element at index i is x.
|
|
--
|
|
-- Note! indexing starts from 0
|
|
--
|
|
-- Examples:
|
|
-- updateAt 0 4 [1,2,3] ==> [4,2,3]
|
|
-- updateAt 2 0 [4,5,6,7] ==> [4,5,0,7]
|
|
|
|
updateAt :: Int -> a -> [a] -> [a]
|
|
updateAt i x xs
|
|
| i >= length xs = xs
|
|
| i == 0 = [x] ++ tail xs
|
|
| otherwise = take i xs ++ [x] ++ drop (i+1) xs
|
|
where ix = xs !! i
|
|
|
|
------------------------------------------------------------------------------
|
|
-- Ex 4: substring i j s should return the substring of s starting at
|
|
-- index i and ending at (right before) index j. Indexes start from 0.
|
|
--
|
|
-- Remember that strings are lists!
|
|
--
|
|
-- Examples:
|
|
-- substring 2 5 "abcdefgh" ==> "cde"
|
|
-- substring 2 2 "abcdefgh" ==> ""
|
|
-- substring 0 4 "abcdefgh" ==> "abcd"
|
|
|
|
substring :: Int -> Int -> String -> String
|
|
substring i j s = drop i (take j s)
|
|
|
|
------------------------------------------------------------------------------
|
|
-- Ex 5: check if a string is a palindrome. A palindrome is a string
|
|
-- that is the same when read backwards.
|
|
--
|
|
-- Hint! There's a really simple solution to this. Don't overthink it!
|
|
--
|
|
-- Examples:
|
|
-- isPalindrome "" ==> True
|
|
-- isPalindrome "ABBA" ==> True
|
|
-- isPalindrome "racecar" ==> True
|
|
-- isPalindrome "AB" ==> False
|
|
|
|
isPalindrome :: String -> Bool
|
|
isPalindrome str = if str == reverse str then True else False
|
|
|
|
------------------------------------------------------------------------------
|
|
-- Ex 6: implement the function palindromify that chops a character
|
|
-- off the front _and_ back of a string until the result is a
|
|
-- palindrome.
|
|
--
|
|
-- Examples:
|
|
-- palindromify "ab" ==> ""
|
|
-- palindromify "aaay" ==> "aa"
|
|
-- palindromify "xabbay" ==> "abba"
|
|
-- palindromify "abracacabra" ==> "acaca"
|
|
|
|
palindromify :: String -> String
|
|
palindromify s
|
|
| s == reverse s = s
|
|
| otherwise = palindromify (tail (init s))
|
|
|
|
------------------------------------------------------------------------------
|
|
-- Ex 7: implement safe integer division, that is, a function that
|
|
-- returns a Just result normally, but Nothing if the divisor is zero.
|
|
--
|
|
-- Remember that integer division can be done with the div function.
|
|
--
|
|
-- Examples:
|
|
-- safeDiv 4 2 ==> Just 2
|
|
-- safeDiv 4 0 ==> Nothing
|
|
|
|
safeDiv :: Integer -> Integer -> Maybe Integer
|
|
safeDiv x y
|
|
| y == 0 = Nothing
|
|
| otherwise = Just(x `div` y)
|
|
|
|
------------------------------------------------------------------------------
|
|
-- Ex 8: implement a function greet that greets a person given a first
|
|
-- name and possibly a last name. The last name is represented as a
|
|
-- Maybe String value.
|
|
--
|
|
-- Examples:
|
|
-- greet "John" Nothing ==> "Hello, John!"
|
|
-- greet "John" (Just "Smith") ==> "Hello, John Smith!"
|
|
|
|
greet :: String -> Maybe String -> String
|
|
greet first Nothing = "Hello, " ++ first ++ "!"
|
|
greet first (Just last) = "Hello, " ++ first ++ " " ++ last ++ "!"
|
|
|
|
------------------------------------------------------------------------------
|
|
-- Ex 9: safe list indexing. Define a function safeIndex so that
|
|
-- safeIndex xs i
|
|
-- gets the element at index i in the list xs. If i is not a valid
|
|
-- index, Nothing is returned.
|
|
--
|
|
-- Examples:
|
|
-- safeIndex [True] 1 ==> Nothing
|
|
-- safeIndex [10,20,30] 0 ==> Just 10
|
|
-- safeIndex [10,20,30] 2 ==> Just 30
|
|
-- safeIndex [10,20,30] 3 ==> Nothing
|
|
-- safeIndex ["a","b","c"] (-1) ==> Nothing
|
|
|
|
safeIndex :: [a] -> Int -> Maybe a
|
|
safeIndex xs i
|
|
| i > length xs-1 || i < 0 = Nothing
|
|
| otherwise = Just(xs !! i)
|
|
|
|
------------------------------------------------------------------------------
|
|
-- Ex 10: another variant of safe division. This time you should use
|
|
-- Either to return a string error message.
|
|
--
|
|
-- Examples:
|
|
-- eitherDiv 4 2 ==> Right 2
|
|
-- eitherDiv 4 0 ==> Left "4/0"
|
|
|
|
eitherDiv :: Integer -> Integer -> Either String Integer
|
|
eitherDiv x y
|
|
| y == 0 = Left(show x ++ "/" ++ show y)
|
|
| otherwise = Right(x `div` y)
|
|
|
|
------------------------------------------------------------------------------
|
|
-- Ex 11: implement the function addEithers, which combines two values of type
|
|
-- Either String Int into one like this:
|
|
--
|
|
-- - If both inputs were Ints, sum the Ints
|
|
-- - Otherwise, return the first argument that was not an Int
|
|
--
|
|
-- Hint! Remember pattern matching
|
|
--
|
|
-- Examples:
|
|
-- addEithers (Right 1) (Right 2) ==> Right 3
|
|
-- addEithers (Right 1) (Left "fail") ==> Left "fail"
|
|
-- addEithers (Left "boom") (Left "fail") ==> Left "boom"
|
|
|
|
addEithers :: Either String Int -> Either String Int -> Either String Int
|
|
addEithers (Right a) (Right b) = Right (a + b)
|
|
addEithers (Left a) (Left b) = Left a
|
|
addEithers (Left a) (Right b) = Left a
|
|
addEithers (Right a) (Left b) = Left b
|