-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathset2b.hs
158 lines (140 loc) · 4.75 KB
/
set2b.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
module Set2b where
import Mooc.Todo
-- Some imports you'll need. Don't add other imports :)
import Data.List
------------------------------------------------------------------------------
-- Ex 1: compute binomial coefficients using recursion. Binomial
-- coefficients are defined by the following equations:
--
-- B(n,k) = B(n-1,k) + B(n-1,k-1)
-- B(n,0) = 1
-- B(0,k) = 0, when k>0
--
-- Hint! pattern matching is your friend.
binomial :: Integer -> Integer -> Integer
binomial _ 0 = 1
binomial 0 _ = 0
binomial n k = binomial (n-1) k + binomial (n-1) (k-1)
------------------------------------------------------------------------------
-- Ex 2: implement the odd factorial function. Odd factorial is like
-- factorial, but it only multiplies odd numbers.
--
-- Examples:
-- oddFactorial 7 ==> 7*5*3*1 ==> 105
-- oddFactorial 6 ==> 5*3*1 ==> 15
oddFactorial :: Integer -> Integer
oddFactorial 1 = 1
oddFactorial 0 = 1
oddFactorial n = if even n then (n-1) * oddFactorial (n-2) else n * oddFactorial(n-2)
------------------------------------------------------------------------------
-- Ex 3: implement the Euclidean Algorithm for finding the greatest
-- common divisor:
--
-- Given two numbers, a and b,
-- * if one is zero, return the other number
-- * if not, subtract the smaller number from the larger one
-- * replace the larger number with this new number
-- * repeat
--
-- For example,
-- myGcd 9 12 ==> 3
-- In this case, the algorithm proceeds like this
--
-- a b
--
-- 9 12
-- 9 (12-9)
-- 9 3
-- (9-3) 3
-- 6 3
-- (6-3) 3
-- 3 3
-- (3-3) 3
-- 0 3
--
-- Background reading:
-- * https://en.wikipedia.org/wiki/Euclidean_algorithm
myGcd :: Integer -> Integer -> Integer
myGcd a 0= a
myGcd 0 a = a
myGcd a b = if myGcd' a b == a then myGcd (a-b) b else myGcd a (b-a)
myGcd' a b = if a > b then a else b
------------------------------------------------------------------------------
-- Ex 4: Implement the function leftpad which adds space characters
-- to the start of the string until it is long enough.
--
-- Examples:
-- leftpad "foo" 5 ==> " foo"
-- leftpad "13" 3 ==> " 13"
-- leftpad "xxxxx" 3 ==> "xxxxx"
--
-- Tips:
-- * you can combine strings with the ++ operator.
-- * you can compute the length of a string with the length function
leftpad :: String -> Int -> String
leftpad s x = if length s < x then leftpad' (x-(length s)) ++ s else s
leftpad' :: Int -> String
leftpad' 0 = []
leftpad' x = " " ++ leftpad'(x -1)
------------------------------------------------------------------------------
-- Ex 5: let's make a countdown for a rocket! Given a number, you
-- should produce a string that says "Ready!", counts down from the
-- number, and then says "Liftoff!".
--
-- For example,
-- countdown 4 ==> "Ready! 4... 3... 2... 1... Liftoff!"
--
-- Hints:
-- * you can combine strings with the ++ operator
-- * you can use the show function to convert a number into a string
-- * you'll probably need a recursive helper function
countdown :: Integer -> String
countdown x = "Ready! " ++ countdown' x ++ "Liftoff!"
countdown' x
|x < 1 = []
|otherwise = show x ++ "... " ++ countdown' (x -1)
------------------------------------------------------------------------------
-- Ex 6: implement the function smallestDivisor that returns the
-- smallest number (greater than 1) that divides the given number evenly.
--
-- That is, when
-- smallestDivisor n ==> k
-- we have
-- n = t*k
-- for some t.
--
-- Ps. your function doesn't need to work for inputs 0 and 1, but
-- remember this in the next exercise!
--
-- Hint: remember the mod function!
smallestDivisor :: Integer -> Integer
smallestDivisor 1 = 1
smallestDivisor 0 = 1
smallestDivisor n = ldf 2 n
ldf :: Integer -> Integer -> Integer
ldf k n | n `rem` k == 0 = k
| k ^ 2 > n = n
| otherwise = ldf (k + 1) n
------------------------------------------------------------------------------
-- Ex 7: implement a function isPrime that checks if the given number
-- is a prime number. Use the function smallestDivisor.
--
-- Ps. 0 and 1 are not prime numbers
isPrime :: Integer -> Bool
isPrime x
|x == 0 = False
|x== 1 = False
|otherwise = if smallestDivisor x == x then True else False
------------------------------------------------------------------------------
-- Ex 8: implement a function biggestPrimeAtMost that returns the
-- biggest prime number that is less than or equal to the given
-- number. Use the function isPrime you just defined.
--
-- You don't need to care about arguments less than 2. Any behaviour
-- for them is fine.
--
-- Examples:
-- biggestPrimeAtMost 3 ==> 3
-- biggestPrimeAtMost 10 ==> 7
biggestPrimeAtMost :: Integer -> Integer
biggestPrimeAtMost x = if isPrime x then x else biggestPrimeAtMost (x -1)