-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathSet14a.hs
140 lines (120 loc) · 4.83 KB
/
Set14a.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
module Set14a where
-- Remember to browse the docs of the Data.Text and Data.ByteString
-- libraries while working on the exercises!
import Mooc.Todo
import Data.Bits
import Data.Char
import Data.Text.Encoding
import Data.Word
import Data.Int
import qualified Data.Text as T
import qualified Data.Text.Lazy as TL
import qualified Data.ByteString as B
import qualified Data.ByteString.Lazy as BL
------------------------------------------------------------------------------
-- Ex 1: Greet a person. Given the name of a person as a Text, return
-- the Text "Hello, <name>!". However, if the name is longer than 15
-- characters, output "Hello, <first 15 characters of the name>...!"
--
-- PS. the test outputs and examples print Text values as if they were
-- Strings, just like GHCi prints Texts as Strings.
--
-- Examples:
-- greetText (T.pack "Martin Freeman") ==> "Hello, Martin Freeman!"
-- greetText (T.pack "Benedict Cumberbatch") ==> "Hello, Benedict Cumber...!"
greetText :: T.Text -> T.Text
greetText name
| T.length name > 15 = T.concat [T.pack "Hello, ", T.take 15 name, T.pack "...!"]
| otherwise = T.concat [T.pack "Hello, ", name, T.pack "!"]
------------------------------------------------------------------------------
-- Ex 2: Capitalize every second word of a Text.
--
-- Examples:
-- shout (T.pack "hello how are you")
-- ==> "HELLO how ARE you"
-- shout (T.pack "word")
-- ==> "WORD"
shout :: T.Text -> T.Text
shout text = T.unwords $ zipWith capitalize [0..] (T.words text)
where
capitalize i word = if even i then T.toUpper word else word
------------------------------------------------------------------------------
-- Ex 3: Find the longest sequence of a single character repeating in
-- a Text, and return its length.
--
-- Examples:
-- longestRepeat (T.pack "") ==> 0
-- longestRepeat (T.pack "aabbbbccc") ==> 4
longestRepeat :: T.Text -> Int
longestRepeat text
| T.null text = 0
| otherwise = maximum . map T.length $ T.group text
------------------------------------------------------------------------------
-- Ex 4: Given a lazy (potentially infinite) Text, extract the first n
-- characters from it and return them as a strict Text.
--
-- The type of the n parameter is Int64, a 64-bit Int. Can you figure
-- out why this is convenient?
--
-- Example:
-- takeStrict 15 (TL.pack (cycle "asdf")) ==> "asdfasdfasdfasd"
takeStrict :: Int64 -> TL.Text -> T.Text
takeStrict n = TL.toStrict . TL.take n
------------------------------------------------------------------------------
-- Ex 5: Find the difference between the largest and smallest byte
-- value in a ByteString. Return 0 for an empty ByteString
--
-- Examples:
-- byteRange (B.pack [1,11,8,3]) ==> 10
-- byteRange (B.pack []) ==> 0
-- byteRange (B.pack [3]) ==> 0
byteRange :: B.ByteString -> Word8
byteRange bs = if B.null bs then 0 else B.maximum bs - B.minimum bs
------------------------------------------------------------------------------
-- Ex 6: Compute the XOR checksum of a ByteString. The XOR checksum of
-- a string of bytes is computed by using the bitwise XOR operation to
-- "sum" together all the bytes.
--
-- The XOR operation is available in Haskell as Data.Bits.xor
-- (imported into this module).
--
-- Examples:
-- xorChecksum (B.pack [137]) ==> 137
-- xor 1 2 ==> 3
-- xorChecksum (B.pack [1,2]) ==> 3
-- xor 1 (xor 2 4) ==> 7
-- xorChecksum (B.pack [1,2,4]) ==> 7
-- xorChecksum (B.pack [13,197,20]) ==> 220
-- xorChecksum (B.pack [13,197,20,197,13,20]) ==> 0
-- xorChecksum (B.pack []) ==> 0
xorChecksum :: B.ByteString -> Word8
xorChecksum bs
| B.null bs = 0
| otherwise = B.foldl' xor (B.head bs) (B.tail bs)
------------------------------------------------------------------------------
-- Ex 7: Given a ByteString, compute how many UTF-8 characters it
-- consists of. If the ByteString is not valid UTF-8, return Nothing.
--
-- Look at the docs of Data.Text.Encoding to find the right functions
-- for this.
--
-- Examples:
-- countUtf8Chars (encodeUtf8 (T.pack "åäö")) ==> Just 3
-- countUtf8Chars (encodeUtf8 (T.pack "wxyz")) ==> Just 4
-- countUtf8Chars (B.pack [195]) ==> Nothing
-- countUtf8Chars (B.pack [195,184]) ==> Just 1
-- countUtf8Chars (B.drop 1 (encodeUtf8 (T.pack "åäö"))) ==> Nothing
countUtf8Chars :: B.ByteString -> Maybe Int
countUtf8Chars bs = case decodeUtf8' bs of
Right text -> Just $ length (T.unpack text)
Left _ -> Nothing
------------------------------------------------------------------------------
-- Ex 8: Given a (nonempty) strict ByteString b, generate an infinite
-- lazy ByteString that consists of b, reversed b, b, reversed b, and
-- so on.
--
-- Example:
-- BL.unpack (BL.take 20 (pingpong (B.pack [0,1,2])))
-- ==> [0,1,2,2,1,0,0,1,2,2,1,0,0,1,2,2,1,0,0,1]
pingpong :: B.ByteString -> BL.ByteString
pingpong bs = BL.fromChunks . cycle $ [bs, B.reverse bs]