Skip to content

Commit 73980ca

Browse files
committed
feat: Ch14 complete
1 parent e7ae1b4 commit 73980ca

File tree

4 files changed

+48
-5
lines changed

4 files changed

+48
-5
lines changed

hffp.cabal

+6-2
Original file line numberDiff line numberDiff line change
@@ -28,17 +28,17 @@ library
2828
Ch14.Addition
2929
Ch14.Morse
3030
Ch8.Playground
31+
Ch11.Cipher
32+
Ch9.Cipher
3133
other-modules:
3234
Ch10.Playground
33-
Ch11.Cipher
3435
Ch11.HuttonsRazor
3536
Ch11.Phone
3637
Ch11.PhoneAlt
3738
Ch11.Playground
3839
Ch12.Playground
3940
Ch13.Person
4041
Ch13.Playground
41-
Ch9.Cipher
4242
Ch9.Playground
4343
Ch9.StdFunc
4444
Lib
@@ -50,6 +50,7 @@ library
5050
default-extensions:
5151
ImportQualifiedPost
5252
LambdaCase
53+
TypeApplications
5354
ghc-options: -Wall -Wcompat -Widentities -Wincomplete-record-updates -Wincomplete-uni-patterns -Wmissing-home-modules -Wpartial-fields -Wredundant-constraints
5455
build-depends:
5556
PyF
@@ -72,6 +73,7 @@ executable hffp
7273
default-extensions:
7374
ImportQualifiedPost
7475
LambdaCase
76+
TypeApplications
7577
ghc-options: -Wall -Wcompat -Widentities -Wincomplete-record-updates -Wincomplete-uni-patterns -Wmissing-home-modules -Wpartial-fields -Wredundant-constraints -threaded -rtsopts -with-rtsopts=-N
7678
build-depends:
7779
base >=4.7 && <5
@@ -82,6 +84,7 @@ test-suite hffp-test
8284
type: exitcode-stdio-1.0
8385
main-is: Spec.hs
8486
other-modules:
87+
Ch14.CipherSpec
8588
Ch14.ExerciseSpec
8689
Ch14.Identity
8790
Ch14.MorseSpec
@@ -95,6 +98,7 @@ test-suite hffp-test
9598
default-extensions:
9699
ImportQualifiedPost
97100
LambdaCase
101+
TypeApplications
98102
ghc-options: -Wall -Wcompat -Widentities -Wincomplete-record-updates -Wincomplete-uni-patterns -Wmissing-home-modules -Wpartial-fields -Wredundant-constraints -threaded -rtsopts -with-rtsopts=-N
99103
build-depends:
100104
QuickCheck

package.yaml

+3
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ dependencies:
2525
default-extensions:
2626
- ImportQualifiedPost
2727
- LambdaCase
28+
- TypeApplications
2829

2930
ghc-options:
3031
- -Wall
@@ -50,6 +51,8 @@ library:
5051
- Ch14.Addition
5152
- Ch14.Morse
5253
- Ch8.Playground
54+
- Ch11.Cipher
55+
- Ch9.Cipher
5356

5457
executables:
5558
hffp:

src/Ch11/Cipher.hs

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
module Ch11.Cipher (vigenereCipher, CaesarCipher.cipherMsg) where
1+
module Ch11.Cipher (vigenereCipher, CaesarCipher.cipherMsg, vigenereUncipher) where
22

33
import Ch9.Cipher qualified as CaesarCipher
44

@@ -9,11 +9,11 @@ type Message = String
99
type CipherText = String
1010

1111
ceilingDivision :: Int -> Int -> Int
12-
ceilingDivision num1 num2 = ceiling . fromIntegral $ div num1 num2
12+
ceilingDivision num1 num2 = (ceiling @Double) . fromIntegral $ div num1 num2
1313

1414
standardizeKeywordLength :: Keyword -> Message -> String
1515
standardizeKeywordLength keyword msg
16-
| length keyword < length msg = let replicateCount = ceilingDivision (length msg) (length keyword) in concat $ replicate replicateCount keyword
16+
| length keyword < length msg = let replicateCount = ceilingDivision (length msg) (length keyword) in concat $ replicate (replicateCount + 1) keyword
1717
| otherwise = keyword
1818

1919
zipWithSpaces :: String -> String -> [(Char, Char)]

test/Ch14/CipherSpec.hs

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
module Ch14.CipherSpec where
2+
3+
import Ch11.Cipher
4+
import Ch9.Cipher
5+
6+
import Test.Hspec
7+
import Test.Hspec.QuickCheck
8+
import Test.QuickCheck
9+
10+
import Data.Char
11+
12+
newtype AlphaChar = AlphaChar {unAlphaChar :: Char} deriving (Eq, Show)
13+
14+
genAlphaChar :: Gen AlphaChar
15+
genAlphaChar = do
16+
let upperCaseAlphaRange = (65, 90)
17+
let lowerCaseAlphaRange = (97, 122)
18+
charCode <- oneof [chooseInt upperCaseAlphaRange, chooseInt lowerCaseAlphaRange]
19+
20+
pure $ AlphaChar $ chr charCode
21+
22+
instance Arbitrary AlphaChar where
23+
arbitrary = genAlphaChar
24+
25+
spec :: Spec
26+
spec = do
27+
describe "Cipher Identity" $ do
28+
prop "Vigenere Cipher" $ \(NonEmpty keyword') (NonEmpty msg') ->
29+
let keyword = unAlphaChar <$> (keyword' :: [AlphaChar])
30+
msg = unAlphaChar <$> (msg' :: [AlphaChar])
31+
in vigenereUncipher keyword (vigenereCipher keyword msg) == msg
32+
33+
prop "Caesar Cipher" $ \(Positive delta') (NonEmpty msg') ->
34+
let delta = (delta' :: Int)
35+
msg = unAlphaChar <$> (msg' :: [AlphaChar])
36+
in unCipherMsg delta (cipherMsg delta msg) == msg

0 commit comments

Comments
 (0)