-
Notifications
You must be signed in to change notification settings - Fork 23
/
lab5.hs
65 lines (50 loc) · 2.09 KB
/
lab5.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
import Data.List (find)
import Data.Maybe (fromMaybe)
import Data.Char (isAlphaNum, toUpper)
-- Permută circular primele `N` caractere dintr-un string.
rotate :: Int -> [Char] -> [Char]
rotate n str
| n < 0 = error "n is negative"
| n > length str = error "n is greater than the string's length"
| otherwise = (drop n str) ++ (take n str)
-- Alfabetul de intrare, care constă în toate literele mari ale alfabetului englez
alphabet :: String
alphabet = ['A'..'Z']
-- Generează cheia de criptare, o listă de perechi care indică
-- ce caracter se duce în care
makeKey :: Int -> [(Char, Char)]
makeKey n = zip alphabet rotated
where
rotated = rotate n alphabet
-- Fiind dat un caracter și o cheie de criptare,
-- găsește caracterul criptat corespunzător.
--
-- Returnează caracterul dat ca parametru dacă nu se poate cripta.
lookUp :: Char -> [(Char, Char)] -> Char
lookUp char key =
let
-- Căutăm perechea corespunzătoare caracterului dat.
wantedPair = find (\(a, _) -> a == char) key
-- Încercăm să extragem caracterul criptat corespunzător,
-- dacă a fost găsită perechea.
wantedChar = fmap snd wantedPair
in
-- Dacă am găsit caracterul criptat îl returnăm,
-- dacă nu returnăm caracterul inițial, necriptat.
fromMaybe char wantedChar
-- Elimină din șir caracterele care nu sunt litere mari sau cifre.
normalize :: String -> String
normalize = map toUpper . filter isAlphaNum
-- Criptează un caracter pentru un anumit N
encipher :: Int -> Char -> Char
encipher n char = lookUp char (makeKey n)
-- Criptează întregul șir normalizat dat ca paremtru, pentru un anumit N
encipherStr :: Int -> String -> String
encipherStr n = map (encipher n) . normalize
-- Pentru decriptare, ne folosim de proprietățile permutărilor circulare.
-- O rotație de lungime M este inversată de una de lungime N - M.
decipher :: Int -> Char -> Char
decipher n = encipher (length alphabet - n)
-- Decriptează tot șirul, ca mai sus
decipherStr :: Int -> String -> String
decipherStr n = map (decipher n) . normalize