-
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Lists.hs
84 lines (69 loc) · 2.1 KB
/
Lists.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
{-# LANGUAGE DerivingStrategies #-}
{-# LANGUAGE InstanceSigs #-}
{-# OPTIONS -Wno-incomplete-patterns #-}
module Lists
( NestedList (..),
myLast,
myButLast,
elementAt,
myLength,
myReverse,
isPalindrome,
flatten,
compress,
pack,
encode,
)
where
import Control.Arrow ((&&&))
import Control.Monad ((<=<))
import qualified Control.Monad as M
import qualified Data.List as L
-- Problem 1: (*) Find the last element of a list.
myLast :: [a] -> a
myLast [] = error "empty list"
myLast [x] = x
myLast xs = myLast (tail xs)
-- Problem 2: (*) Find the last-but-one (or second-last) element of a list.
myButLast :: [a] -> a
myButLast [] = error "empty list"
myButLast [x, _] = x
myButLast xs = myButLast (tail xs)
-- Problem 3: (*) Find the K'th element of a list.
elementAt :: [a] -> Int -> a
elementAt [] _ = error "empty list"
elementAt (x : _) 1 = x
elementAt xs k = elementAt (tail xs) (k - 1)
-- Problem 4: (*) Find the number of elements in a list.
myLength :: [a] -> Int
myLength = foldl (const . succ) 0
-- Problem 5: (*) Reverse a list.
myReverse :: [a] -> [a]
myReverse = foldl (flip (:)) []
-- Problem 6: (*) Find out whether a list is a palindrome.
isPalindrome :: (Eq a) => [a] -> Bool
isPalindrome = M.ap (==) myReverse
data NestedList a = Elem a | List [NestedList a]
deriving stock (Show)
instance Foldable NestedList where
foldr :: (a -> b -> b) -> b -> NestedList a -> b
foldr f acc x = case x of
Elem y -> f y acc
List xs -> L.foldr (flip (foldr f)) acc xs
-- Problem 7: (**) Flatten a nested list structure.
flatten :: NestedList a -> [a]
flatten = foldr (:) []
-- Problem 8: (**) Eliminate consecutive duplicates of list elements.
compress :: (Eq a) => [a] -> [a]
compress = take 1 <=< pack
-- Problem 9: (**) Pack consecutive duplicates of list elements into sublists.
pack :: (Eq a) => [a] -> [[a]]
pack = foldr go []
where
go x [] = [[x]]
go x xxs@(ys@(y : _) : zs)
| x == y = (x : ys) : zs
| otherwise = [x] : xxs
-- Problem 10: (*) Run-length encoding of a list.
encode :: (Eq a) => [a] -> [(Int, a)]
encode = map (length &&& head) . pack