-
Notifications
You must be signed in to change notification settings - Fork 0
/
cipher.hs
55 lines (40 loc) · 1.57 KB
/
cipher.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
-- Caeser's Cipher Example from 4.10 of the Future Learn Haskell MOOC
import Data.Char
-- is this a letter to be ciphered?
shouldcipher :: Char -> Bool
shouldcipher c = isLetter(c) && isAscii(c)
-- encipher single char at a time
cipherchar :: Int -> Char -> Char
cipherchar shift c
| shouldcipher c = chr(ord(c)+shift)
| otherwise = c
-- encipher a whole string
cipher :: Int -> [Char] -> [Char]
--cipher shift plaintext = map (cipherchar shift) plaintext
cipher shift plaintext = map (bettercipherchar shift) plaintext
decipher :: Int-> [Char] -> [Char]
decipher shift ciphertext = cipher (-shift) ciphertext
-- import Test.QuickCheck
-- quickCheck ((\n -> (\s ->((decipher n (cipher n s)) == s))) :: Int -> [Char] -> Bool)
-- *** Failed! Falsifiable (after 13 tests and 4 shrinks):
-- 9
-- "r"
-- should we wrap around the alphabet?
wraparound shift c
| isLower(c) && ord(c)+shift > ord 'z' = True
| isUpper(c) && ord(c)+shift > ord 'Z' = True
| otherwise = False
bettercipherchar :: Int -> Char -> Char
bettercipherchar shift c
| shouldcipher c = chr(ord(c) + adjustedshift)
| otherwise = c
where adjustedshift = let shift' = shift `mod` 26
in if (wraparound shift' c)
then shift'-26
else shift'
-- quickCheck ((\n -> (\s ->((decipher n (cipher n s)) == s))) :: Int -> [Char] -> Bool)
-- +++ OK, passed 100 tests.
-- verboseCheck ((\n -> (\s ->((decipher n (cipher n s)) == s))) :: Int -> [Char] -> Bool)
--
-- Testing can only show the presence of bugs, not their absence.
-- -Edgar Dijkstra