-
Notifications
You must be signed in to change notification settings - Fork 1
/
set3b.hs
209 lines (185 loc) · 6.6 KB
/
set3b.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
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
-- Exercise set 3b
--
-- This is a special exercise set. The exercises are about
-- implementing list functions using recursion and pattern matching,
-- without using any standard library functions. For this reason,
-- you'll be working in a limited environment where almost none of the
-- standard library is available.
--
-- At least the following standard library functions are missing:
-- * (++)
-- * head
-- * tail
-- * map
-- * filter
-- * concat
-- * (!!)
--
-- The (:) operator is available, as is list literal syntax [a,b,c].
--
-- Feel free to use if-then-else, guards, and ordering functions (< and > etc.).
--
-- The tests will check that you haven't added imports :)
{-# LANGUAGE NoImplicitPrelude #-}
module Set3b where
import Mooc.LimitedPrelude
import Mooc.Todo
------------------------------------------------------------------------------
-- Ex 1: given numbers start, count and end, build a list that starts
-- with count copies of start and ends with end.
--
-- Use recursion and the : operator to build the list.
--
-- Examples:
-- buildList 1 5 2 ==> [1,1,1,1,1,2]
-- buildList 7 0 3 ==> [3]
buildList :: Int -> Int -> Int -> [Int]
buildList _ 0 end = end:[]
buildList start count end = start: buildList start (count -1) end
------------------------------------------------------------------------------
-- Ex 2: given i, build the list of sums [1, 1+2, 1+2+3, .., 1+2+..+i]
--
-- Use recursion and the : operator to build the list.
--
-- Ps. you'll probably need a recursive helper function
sums :: Int -> [Int]
sums i = go 0 1
where go sum j
| j > i = []
| otherwise = (sum + j) : go (sum + j) (j + 1)
------------------------------------------------------------------------------
-- Ex 3: define a function mylast that returns the last value of the
-- given list. For an empty list, a provided default value is
-- returned.
--
-- Use only pattern matching and recursion (and the list constructors : and [])
--
-- Examples:
-- mylast 0 [] ==> 0
-- mylast 0 [1,2,3] ==> 3
mylast :: a -> [a] -> a
mylast a [] = a
mylast a (x:[]) = x
mylast def (x:xs) = mylast def xs
------------------------------------------------------------------------------
-- Ex 4: safe list indexing. Define a function indexDefault so that
-- indexDefault xs i def
-- gets the element at index i in the list xs. If i is not a valid
-- index, def is returned.
--
-- Use only pattern matching and recursion (and the list constructors : and [])
--
-- This time, implement indexDefault using pattern matching and
-- recursion.
--
-- Examples:
-- indexDefault [True] 1 False ==> False
-- indexDefault [10,20,30] 0 7 ==> 10
-- indexDefault [10,20,30] 2 7 ==> 30
-- indexDefault [10,20,30] 3 7 ==> 7
-- indexDefault ["a","b","c"] (-1) "d" ==> "d"
indexDefault :: [a] -> Int -> a -> a
indexDefault [] _ def = def
indexDefault (x:xs) i def = if i== 0 then x else indexDefault xs (i-1) def
------------------------------------------------------------------------------
-- Ex 5: define a function that checks if the given list is in
-- increasing order.
--
-- Use pattern matching and recursion to iterate through the list.
sorted :: [Int] -> Bool
sorted [] = True
sorted (x:[]) = True
sorted (x:y:xs) | x <= y = sorted (y:xs)
| otherwise = False
------------------------------------------------------------------------------
-- Ex 6: compute the partial sums of the given list like this:
--
-- sumsOf [a,b,c] ==> [a,a+b,a+b+c]
-- sumsOf [a,b] ==> [a,a+b]
-- sumsOf [] ==> []
--
-- Use pattern matching and recursion (and the list constructors : and [])
sumsOf :: [Int] -> [Int]
sumsOf [] = []
sumsOf xs = go 0 xs
where go acc (x:xs) = (acc + x) : go (acc + x) xs
go _ _ = []
------------------------------------------------------------------------------
-- Ex 7: implement the function merge that merges two sorted lists of
-- Ints into a sorted list
--
-- Use only pattern matching and recursion (and the list constructors : and [])
--
-- Examples:
-- merge [1,3,5] [2,4,6] ==> [1,2,3,4,5,6]
-- merge [1,1,6] [1,2] ==> [1,1,1,2,6]
merge :: [Int] -> [Int] -> [Int]
merge [] [] = []
merge [] a = a
merge a [] = a
merge (x:[]) [] = [x]
merge [] (y:[]) = [y]
merge (x:xs) (y:ys)
| x <= y = x:merge xs (y:ys)
|otherwise = y:merge (x:xs) ys
------------------------------------------------------------------------------
-- Ex 8: define the function mymaximum that takes a list and a
-- function bigger :: a -> a -> Bool and returns the
-- biggest of the list, according to the comparing function.
--
-- An initial biggest value is provided to give you something to
-- return for empty lists.
--
-- Examples:
-- mymaximum (>) 3 [] ==> 3
-- mymaximum (>) 0 [1,3,2] ==> 3
-- mymaximum (>) 4 [1,3,2] ==> 4 -- initial value was biggest
-- mymaximum (<) 4 [1,3,2] ==> 1 -- note changed biggerThan
-- mymaximum (\xs ys -> length xs > length ys) [] [[1,2],[3]]
-- ==> [1,2]
mymaximum :: (a -> a -> Bool) -> a -> [a] -> a
mymaximum _ x [] = x
mymaximum bigger x (y:[]) = if bigger x y then x else y
mymaximum bigger initial (x:y:xs)
| bigger x y = mymaximum bigger initial (x:xs)
| otherwise = mymaximum bigger initial (y:xs)
------------------------------------------------------------------------------
-- Ex 9: define a version of map that takes a two-argument function
-- and two lists. Example:
--
-- map2 f [x,y,z,w] [a,b,c] ==> [f x a, f y b, f z c]
--
-- If the lists have differing lengths, ignore the trailing elements
-- of the longer list.
--
-- Use recursion and pattern matching. Do not use any library functions.
map2 :: (a -> b -> c) -> [a] -> [b] -> [c]
map2 f (x:xs) [] = []
map2 f [] (y:xs) = []
map2 f [] [] = []
map2 f (x:as) (y:bs) = (f x y):map2 f as bs
------------------------------------------------------------------------------
-- Ex 10: implement the function maybeMap, which works a bit like a
-- combined map & filter.
---
-- maybeMap is given a list ([a]) and a function of type a -> Maybe b.
-- This function is called for all values in the list. If the function
-- returns Just x, x will be in the result list. If the function
-- returns Nothing, no value gets added to the result list.
--
-- Examples:
--
-- let f x = if x>0 then Just (2*x) else Nothing
-- in maybeMap f [0,1,-1,4,-2,2]
-- ==> [2,8,4]
--
-- maybeMap Just [1,2,3]
-- ==> [1,2,3]
--
-- maybeMap (\x -> Nothing) [1,2,3]
-- ==> []
maybeMap :: (a -> Maybe b) -> [a] -> [b]
maybeMap f [] = []
maybeMap f (x:xs) = case f x of
Just value -> value: maybeMap f xs
Nothing -> maybeMap f xs