-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathFirstVariationOnCaesarCipher.hs
More file actions
92 lines (66 loc) · 2.75 KB
/
FirstVariationOnCaesarCipher.hs
File metadata and controls
92 lines (66 loc) · 2.75 KB
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
module FirstVariationOnCaesarCipher where
import Data.Char ( ord, chr, isLower, isUpper )
import Data.List.Split ( chunksOf )
upperStartsAt :: Int
upperStartsAt = ord 'A'
lowerStartsAt :: Int
lowerStartsAt = ord 'a'
lettersCount :: Int
lettersCount = ord 'z' - ord 'a' + 1
moveChar :: Int -> (Int -> Int) -> Char -> Char
moveChar
charStartsAt
modifyNumber
characterToMove = chr resultingIndex
where
resultingIndex = resultingIndexFrom0 + charStartsAt
resultingIndexFrom0 = mod (modifyNumber charIndexFrom0) lettersCount
charIndexFrom0 = charIndex - charStartsAt
charIndex = ord characterToMove
-- More functional WAY
moveCharFP1 :: Int -> (Int -> Int) -> Char -> Char
moveCharFP1
charStartsAt
modifyNumber = chr . (+ charStartsAt) . flip mod lettersCount . modifyNumber . flip (-) charStartsAt . ord
-- 100% FP :D
moveCharFP100 :: Int -> (Int -> Int) -> Char -> Char
moveCharFP100 x y = chr . (+ x) . flip mod 26 . y . flip (-) x . ord
moveUpperChar :: (Int -> Int) -> Char -> Char
moveUpperChar = moveChar upperStartsAt
moveLowerChar :: (Int -> Int) -> Char -> Char
moveLowerChar = moveChar lowerStartsAt
moveCharBy :: (Int -> Int) -> Char -> Char
moveCharBy i x
| isUpper x = moveUpperChar i x
| isLower x = moveLowerChar i x
| otherwise = x
moveCharacterInPairByIndexModifier :: (Int -> Int -> Int) -> (Int, Char) -> Char
moveCharacterInPairByIndexModifier i x = moveCharBy (i $ fst x) (snd x)
withIndexes :: String -> [(Int, Char)]
withIndexes = zip [0..]
encode :: String -> Int -> String
encode x i = map (moveCharacterInPairByIndexModifier changeIndex) $ withIndexes x
where changeIndex = \x y -> i + x + y
decode :: String -> Int -> String
decode x i = map (moveCharacterInPairByIndexModifier changeIndex) $ withIndexes x
where changeIndex = \x y -> y - (i + x)
getDivider :: String -> Int
getDivider x = ceiling ( fromIntegral (length x) / 5 ) :: Int
brakeString :: String -> [String]
brakeString x = chunksOf (getDivider x) x
movingShift :: String -> Int -> [String]
movingShift input moveAt = take 5 $ brakeString (encode input moveAt) ++ [""]
-- This how it should have been written ))
movingShiftFP :: String -> Int -> [String]
movingShiftFP input moveAt = take 5 . (++ [""]) $ brakeString (encode input moveAt)
demovingShift :: [String] -> Int -> String
demovingShift input = decode (concat input)
-- Examples to test on!
source :: [Char]
source = "I should have known that you would have a perfect answer for me!!!"
expected :: [[Char]]
expected = ["J vltasl rlhr ","zdfog odxr ypw"," atasl rlhr p ","gwkzzyq zntyhv"," lvz wp!!!"]
shift :: Int -> Int -> Int
shift x y = x * 100 + y
-- This could have fixed need to zip array with index array and using pairs
test2 n = zipWith shift [n, n+1..] $ [5,7,9]