haskell_playground/app/Problems.hs
2024-12-05 12:43:06 +01:00

99 lines
3.0 KiB
Haskell

module Problems ( myLast, lastTwo, kth, myLength, rev, isPalindrome, flatten, NestedList(..), compress, pack, encode ) where
-- H99: Ninety-Nine Haskell Problems
-- https://wiki.haskell.org/H-99:_Ninety-Nine_Haskell_Problems
-- Find the last element of a list.
myLast :: [t] -> Maybe t
myLast [] = Nothing
myLast [x] = Just x
myLast (x:xs) = myLast xs
-- Find the last but one element of a list.
lastTwo :: [t] -> Maybe (t, t)
lastTwo [] = Nothing
lastTwo [x] = Nothing
lastTwo [x, y] = Just(x, y)
lastTwo (x:y:xs) = lastTwo xs
-- Find the K'th element of a list. The first element in the list is number 1.
kth :: [t] -> Int -> Maybe t
kth [] _ = Nothing
kth (x:xs) n = if n == 0 then Just x else kth xs (n - 1)
-- Find the number of elements of a list.
myLength :: [t] -> Int
myLength [] = 0
--myLength (_:xs) = 1 + myLength xs
myLength (_:xs) = subMyLength xs 0 + 1
where
subMyLength :: [t] -> Int -> Int
subMyLength [] n = n
subMyLength (_:ys) n = subMyLength ys (n + 1)
-- Reverse a list
rev :: [t] -> [t]
rev [] = []
rev (x:xs) = rev xs ++ [x]
-- Palindrome
isPalindrome :: (Eq t) => [t] -> Bool
isPalindrome [] = True
--isPalindrome (x:xs) = (x == y) && equal_list xs ys
-- where
-- equal_list :: [t] -> [t] -> Bool
-- equal_list [] [] = True
-- equal_list (x1:x1s) (y1:y1s) = (x1 == y1) && equal_list x1s y1s
-- (y:ys) = rev (x:xs)
isPalindrome (x:xs) = (x == y) && (xs == ys)
where (y:ys) = rev (x:xs)
-- Flatten a list
data NestedList a = Elem a | List [NestedList a]
flatten :: NestedList a -> [a]
flatten (List []) = []
flatten (Elem a) = [a]
flatten (List (x:xs)) = flatten x ++ flatten (List xs)
-- Eliminate consecutive duplicates of list elements.
-- compress :: (Eq t) => [t] -> [t]
-- compress [] = []
-- compress [x] = [x]
-- compress (x:xs) = x : unique x xs
-- where
-- unique :: (Eq t) => t -> [t] -> [t]
-- unique _ [] = []
-- unique x (y:ys) = if x == y then unique y ys else y : unique y ys
compress :: (Eq t) => [t] -> [t]
compress (x:ys@(y:_)) = if x == y then compress ys else x : compress ys
compress x = x
-- Pack consecutive duplicates of list elements into sublists.
-- If a list contains repeated elements they should be placed in separate sublists.
--pack :: (Eq t) => [t] -> [[t]]
--pack [] = [[]]
--pack [x] = [[x]]
--pack (x:y:xs)
-- | x == y = [x,y] : pack xs
-- | otherwise = [x] : [y] : pack xs
pack :: (Eq t) => [t] -> [[t]]
pack [] = []
pack (x:xs) = (x:first) : pack rest
where
getReps [] = ([], [])
getReps (y:ys)
| y == x = let (f, r) = getReps ys in (y:f, r)
| otherwise = ([], y:ys)
(first, rest) = getReps xs
-- Run-length encoding of a list.
-- Use the result of problem P09 to implement the so-called run-length encoding data compression method.
-- Consecutive duplicates of elements are encoded as lists (N E) where N is the number of duplicates of the element E.
encode :: (Eq t) => [t] -> [(Int, t)]
encode [] = []
-- encode (x:xs) = [(n,e) | ]
-- where
-- y:ys = pack (x:xs)