From 80066909582af65dbb692f0cd738bc23ea71f325 Mon Sep 17 00:00:00 2001 From: Dimitar Byalkov Date: Fri, 8 Mar 2024 19:44:08 +0100 Subject: [PATCH] caesar3 tests and comments --- wk3/src/Caesar3.elm | 44 +++++++++++++++++++++++++++++++++++---- wk3/src/TestsCaesar3.png | Bin 0 -> 15178 bytes 2 files changed, 40 insertions(+), 4 deletions(-) create mode 100644 wk3/src/TestsCaesar3.png diff --git a/wk3/src/Caesar3.elm b/wk3/src/Caesar3.elm index 98a8dc5..cdc3631 100644 --- a/wk3/src/Caesar3.elm +++ b/wk3/src/Caesar3.elm @@ -8,21 +8,31 @@ import Caesar2 exposing (..) Dimitar Byalkov and Kaloyan Stoykov -} +-- Start value is 1, so the Brute Generator function can generate all possible decrypted strings +accumulatorStart: Int +accumulatorStart = 1 + +-- End value is 25 => the strings are decrypted with keys 1-25 +accumulatorEnd: Int +accumulatorEnd = 25 + candidates: List String -> String -> List (Int, String) candidates canaries encryptedText = case canaries of [] -> [] x :: xs -> - filterList x (bruteGenerator encryptedText 0) ++ candidates (List.drop 1 canaries) encryptedText + filterList x (bruteGenerator encryptedText accumulatorStart) ++ candidates (List.drop 1 canaries) encryptedText +-- The Brute Generator generates all possible decrypted strings from a given start value bruteGenerator: String -> Int -> List (Int, String) bruteGenerator encryptedText accumulator = - if accumulator < 25 then + if accumulator < accumulatorEnd then (accumulator, (decrypt accumulator encryptedText)) :: bruteGenerator encryptedText (accumulator + 1) else List.singleton (accumulator, (decrypt accumulator encryptedText)) - + +-- Filters a given list of tuples' second value by a given key (canary) filterList: String -> List (Int, String) -> List (Int, String) filterList canary candidateTexts = case candidateTexts of @@ -38,7 +48,33 @@ containsText: String -> String -> Bool containsText canary text = if String.left (String.length canary) text == canary then True + -- Necessary to prevent a RangeError: Maximum call stack exceeded else if String.length text == 0 then False else - containsText canary (String.dropLeft 1 text) \ No newline at end of file + containsText canary (String.dropLeft 1 text) + +-- Tests +testContainsText: Bool +testContainsText = + containsText "THE" "OVERTHELAZYDOG" + +testContainsTextNot: Bool +testContainsTextNot = + not (containsText "AND" "OVERTHELAZYDOG") + +testBruteGenerator: Bool +testBruteGenerator = + bruteGenerator "AA" 1 == [(1,"ZZ"),(2,"YY"),(3,"XX"),(4,"WW"),(5,"VV"),(6,"UU"),(7,"TT"),(8,"SS"),(9,"RR"),(10,"QQ"),(11,"PP"),(12,"OO"),(13,"NN"),(14,"MM"),(15,"LL"),(16,"KK"),(17,"JJ"),(18,"II"),(19,"HH"),(20,"GG"),(21,"FF"),(22,"EE"),(23,"DD"),(24,"CC"),(25,"BB")] + +testFilterList: Bool +testFilterList = + filterList "THE" (bruteGenerator "BPMYCQKSJZWEVNWF" 0) == [(8,"THEQUICKBROWNFOX")] + +testCandidates: Bool +testCandidates = + candidates ["THE", "AND"] "DGGADBCOOCZYMJHZYVMTOJOCZHVS" == [(5, "YBBVYWXJJXUTHECUTQHOJEJXUCQN"), (14,"PSSMPNOAAOLKYVTLKHYFAVAOLTHE"), (21,"ILLFIGHTTHEDROMEDARYTOTHEMAX")] + +allCaesar3Tests: List Bool +allCaesar3Tests = + [testContainsText, testContainsTextNot, testBruteGenerator, testFilterList, testCandidates] \ No newline at end of file diff --git a/wk3/src/TestsCaesar3.png b/wk3/src/TestsCaesar3.png new file mode 100644 index 0000000000000000000000000000000000000000..0592a6205bd276ece1121717e380e51af8c8af1c GIT binary patch literal 15178 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 z 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