@ 99cbaa37b7ae18ff97b86fb15e60808434311257 | history
-- 1. Implement `last`
myLast :: [a] -> a
myLast [] = error "Empty list"
myLast [x] = x
myLast (x:xs) = myLast xs
myLast' :: [a] -> a
myLast' = head . reverse
-- 2. Write a function that returns the penultimate item in a list
myButLast :: [a] -> a
myButLast list
| len < 2 = error "Too few elements!"
| otherwise = list !! (len - 2)
where len = length list
-- 3. Implement `!!`
elementAt :: [a] -> Int -> a
elementAt list index
| index < 1 = error "Index must be a positive number!"
| length list < index = error "List index out of range!"
| otherwise = myLast $ take index list
-- But this doesn't work for infinite lists!
elementAt' :: [a] -> Int -> a
elementAt' list index
| index < 1 = error "Index must be a positive number!"
| null elementAtHead = error "List index out of range!"
| otherwise = head elementAtHead
where elementAtHead = drop (index - 1) list
-- This works fine for infinite lists
-- 4. Implement `length`
myLength :: [a] -> Int
myLength [] = 0
myLength (x:xs) = 1 + myLength xs
-- 5. Implement `reverse`
myReverse :: [a] -> [a]
myReverse [] = []
myReverse [x] = [x]
myReverse list = (myLast list):(myReverse $ init list)
-- 6. Write a function to determine whether a list is a palindrome
isPalindrome :: Eq a => [a] -> Bool
isPalindrome list = myReverse list == list
isPalindrome' :: Eq a => [a] -> Bool
isPalindrome' [] = True
isPalindrome' [x] = True
isPalindrome' list = ((head list) == (last list))
&& (isPalindrome' (init $ tail list))
-- 7. Flatten an arbitrarily-nested list
data NestedList a = Elem a | List [NestedList a]
flatten :: NestedList a -> [a]
flatten (Elem x) = [x]
flatten (List []) = []
flatten (List (x:xs)) = (flatten x) ++ (flatten $ List xs)
-- 8. Collapse adjacent identical list elements to a single element
compress :: Eq a => [a] -> [a]
compress [] = []
compress [x] = [x]
compress (x:xs) = if x == head xs
then compress xs
else x:(compress xs)
-- 9. Separate runs of identical elements into sublists
pack :: Eq a => [a] -> [[a]]
pack [] = []
pack (x:xs) = (x : (takeWhile (== x) xs)) : pack (dropWhile (== x) xs)
pack' :: Eq a => [a] -> [[a]]
pack' [] = []
pack' (x:xs) = (x : fst run) : (pack $ snd run)
where run = span (== x) xs
-- 10. Encode runs of identical elements into tuples:
-- (<number of elements in run>, <element>)
encode :: Eq a => [a]-> [(Int, a)]
encode = map (\l -> (length l, head l)) . pack