From 37e40640a0208141fd7d83f24c95e74e82e1b2af Mon Sep 17 00:00:00 2001 From: Smaug123 Date: Mon, 4 Jan 2016 09:31:35 +0000 Subject: [PATCH] Enforce lower/uppercase consistency; expand readme --- README.md | 42 ++++++++++++++++++++++++++++++++++++++++-- src/caesar.jl | 11 ++++++----- src/monoalphabetic.jl | 5 ++--- src/vigenere.jl | 11 +++++------ test/monoalphabetic.jl | 2 +- test/solitaire.jl | 24 ++++++++++++------------ test/vigenere.jl | 11 +++++------ 7 files changed, 71 insertions(+), 35 deletions(-) diff --git a/README.md b/README.md index cbff3fb..72df5c7 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,5 @@ +[![Build Status](https://travis-ci.org/Smaug123/ClassicalCiphers.jl.svg?branch=master)](https://travis-ci.org/Smaug123/ClassicalCiphers.jl) + # ClassicalCiphers ## Main Features @@ -12,9 +14,45 @@ The Solitaire cipher is included for completeness, though it is perhaps not stri * [Vigenère] * [Solitaire] +## Gotchas + +In general, `encrypt` functions turn text upper-case, while `decrypt` functions +turn text lower-case. +This is consistent with convention, but may not be expected. + +## Code samples + +### Caesar cipher + +Encrypt the text "Hello, World!" with a Caesar offset of 3 (that is, sending + 'a' to 'd'): +```julia +encrypt_caesar("Hello, World!", 3) +# outputs "khoor, zruog!" +``` + +Notice that `encrypt_caesar` turns everything upper-case, but retains symbols. + +Decrypt the same text: +```julia +decrypt_caesar("Khoor, Zruog!", 3) +# outputs "hello, world!" +``` + +Likewise, `decrypt_caesar` turns everything lower-case, but retains symbols. + +### Monoalphabetic cipher + +Encrypt the text "Hello, World!" with the same Caesar cipher, but +viewed as a monoalphabetic substitution: + +```julia +encrypt_monoalphabetic("Hello, World!", "DEFGHIJKLMNOPQRSTUVWXYZABC") +# outputs "KHOOR, ZRUOG!" +``` + + [Caesar]: https://en.wikipedia.org/wiki/Caesar_cipher [Vigenère]: https://en.wikipedia.org/wiki/Vigen%C3%A8re_cipher [Monoalphabetic substitution]: https://en.wikipedia.org/wiki/Substitution_cipher [Solitaire]: https://en.wikipedia.org/wiki/Solitaire_(cipher) - -[![Build Status](https://travis-ci.org/Smaug123/ClassicalCiphers.jl.svg?branch=master)](https://travis-ci.org/Smaug123/ClassicalCiphers.jl) diff --git a/src/caesar.jl b/src/caesar.jl index 827c85e..c3c0bee 100644 --- a/src/caesar.jl +++ b/src/caesar.jl @@ -1,14 +1,15 @@ """ Encrypts the given plaintext according to the Caesar cipher. The key is given as an integer, being the offset of each character; -so encrypt_caesar("abc", 1) == "bcd". +so encrypt_caesar("abc", 1) == "BCD". -Converts the input to lowercase. +Converts the input to uppercase. """ function encrypt_caesar(plaintext, key::Integer) # plaintext: string; key: integer offset, so k=1 sends "a" to "b" key = ((key-1) % 26) + 1 - encrypt_monoalphabetic(plaintext, join([collect(Char(97+key):'z'); collect('a':Char(97+key-1))])) + keystr = join([collect(Char(97+key):'z'); collect('a':Char(97+key-1))]) + encrypt_monoalphabetic(plaintext, keystr) end """ @@ -19,7 +20,7 @@ so decrypt_caesar("abcd", 1) == "zabc". Converts the input to lowercase. """ function decrypt_caesar(ciphertext, key::Integer) - # ciphertext: string; key: integer offset, so k=1 decrypts "B" as "A" + # ciphertext: string; key: integer offset, so k=1 decrypts "B" as "a" key = ((key-1) % 26) + 1 - encrypt_caesar(ciphertext, 26-key) + lowercase(encrypt_caesar(ciphertext, 26-key)) end diff --git a/src/monoalphabetic.jl b/src/monoalphabetic.jl index de3ebef..32e6880 100644 --- a/src/monoalphabetic.jl +++ b/src/monoalphabetic.jl @@ -35,9 +35,8 @@ end function encrypt_monoalphabetic(plaintext, key::AbstractString) # plaintext: string; key: string of length 26, first character is the image of 'a', etc # working in lowercase; key is assumed only to have each element appearing once - # and to be in lowercase. - dict = Dict{Char, Char}(map(x -> (x[1]+96, x[2]), enumerate(key))) - encrypt_monoalphabetic(lowercase(plaintext), dict) + dict = Dict{Char, Char}(map(x -> (x[1]+64, x[2]), enumerate(uppercase(key)))) + encrypt_monoalphabetic(uppercase(plaintext), dict) end function decrypt_monoalphabetic(ciphertext, key::AbstractString) diff --git a/src/vigenere.jl b/src/vigenere.jl index d10a5f3..965d078 100644 --- a/src/vigenere.jl +++ b/src/vigenere.jl @@ -1,6 +1,6 @@ """ Encrypts the given string using the Vigenere cipher according to the given vector of offsets. -For example, encrypt_vigenere("ab", [0, 1]) returns "ac". +For example, encrypt_vigenere("ab", [0, 1]) returns "AC". """ function encrypt_vigenere(plaintext, key::Array) # plaintext: string; key: vector of integer offsets, so [0, 1] encrypts "ab" as "ac" @@ -16,16 +16,15 @@ For example, decrypt_vigenere("ac", [0, 1]) returns "ab". """ function decrypt_vigenere(ciphertext, key::Array) # ciphertext: string; key: vector of integer offsets, so [0, 1] decrypts "ac" as "ab" - encrypt_vigenere(ciphertext, 26-key) + lowercase(encrypt_vigenere(ciphertext, 26-key)) end """ Encrypts the given string using the Vigenere cipher according to the given keystring. -For example, encrypt_vigenere("ab", "ab") returns "ac". +For example, encrypt_vigenere("ab", "ab") returns "AC". """ function encrypt_vigenere(ciphertext, key::AbstractString) - # ciphertext: string; key: string, so "ab" encrypts "ab" as "ac" - + # ciphertext: string; key: string, so "ab" encrypts "ab" as "AC" encrypt_vigenere(ciphertext, [Int(i)-97 for i in lowercase(letters_only(key))]) end @@ -36,4 +35,4 @@ For example, decrypt_vigenere("ab", "ac") returns "ab". function decrypt_vigenere(plaintext, key::AbstractString) # plaintext: string; key: string, so "ab" decrypts "ac" as "ab" decrypt_vigenere(plaintext, [Int(i)-97 for i in lowercase(letters_only(key))]) -end \ No newline at end of file +end diff --git a/test/monoalphabetic.jl b/test/monoalphabetic.jl index 67b3758..5e7049b 100644 --- a/test/monoalphabetic.jl +++ b/test/monoalphabetic.jl @@ -10,6 +10,6 @@ using Base.Test @test decrypt_monoalphabetic("WKLV FRGH ZDV LQYHQWHG EB MXOLXV FDHVDU", "DEFGHIJKLMNOPQRSTUVWXYZABC") == lowercase("THIS CODE WAS INVENTED BY JULIUS CAESAR") -@test encrypt_caesar("THIS CODE WAS INVENTED BY JULIUS CAESAR", 3) == lowercase("WKLV FRGH ZDV LQYHQWHG EB MXOLXV FDHVDU") +@test encrypt_caesar("THIS CODE WAS INVENTED BY JULIUS CAESAR", 3) == "WKLV FRGH ZDV LQYHQWHG EB MXOLXV FDHVDU" @test decrypt_caesar("WKLV FRGH ZDV LQYHQWHG EB MXOLXV FDHVDU", 3) == lowercase("THIS CODE WAS INVENTED BY JULIUS CAESAR") diff --git a/test/solitaire.jl b/test/solitaire.jl index 480a78c..98b8251 100644 --- a/test/solitaire.jl +++ b/test/solitaire.jl @@ -1,18 +1,18 @@ using ClassicalCiphers using Base.Test -@test encrypt_solitaire("aaaaaaaaaaaaaaa", "") == lowercase("EXKYIZSGEHUNTIQ") -@test encrypt_solitaire("aaaaaaaaaaaaaaa", "f") == lowercase("XYIUQBMHKKJBEGY") -@test encrypt_solitaire("AAAAAAAAAAAAAAA", "fo") == lowercase("TUJYMBERLGXNDIW") -@test encrypt_solitaire("AAAAAAAAAAAAAAA", "foo") == lowercase("ITHZUJIWGRFARMW") -@test encrypt_solitaire("AAAAAAAAAAAAAAA", "a") == lowercase("XODALGSCULIQNSC") -@test encrypt_solitaire("AAAAAAAAAAAAAAA", "aa") == lowercase("OHGWMXXCAIMCIQP") -@test encrypt_solitaire("AAAAAAAAAAAAAAA", "aaa") == lowercase("DCSQYHBQZNGDRUT") -@test encrypt_solitaire("AAAAAAAAAAAAAAA", "b") == lowercase("XQEEMOITLZVDSQS") -@test encrypt_solitaire("AAAAAAAAAAAAAAA", "bc") == lowercase("QNGRKQIHCLGWSCE") -@test encrypt_solitaire("AAAAAAAAAAAAAAA", "bcd") == lowercase("FMUBYBMAXHNQXCJ") -@test encrypt_solitaire("AAAAAAAAAAAAAAAAAAAAAAAAA", "cryptonomicon") == lowercase("SUGSRSXSWQRMXOHIPBFPXARYQ") -@test encrypt_solitaire("SOLITAIREX", "cryptonomicon") == lowercase("KIRAKSFJAN") +@test encrypt_solitaire("aaaaaaaaaaaaaaa", "") == "EXKYIZSGEHUNTIQ" +@test encrypt_solitaire("aaaaaaaaaaaaaaa", "f") == "XYIUQBMHKKJBEGY" +@test encrypt_solitaire("AAAAAAAAAAAAAAA", "fo") == "TUJYMBERLGXNDIW" +@test encrypt_solitaire("AAAAAAAAAAAAAAA", "foo") == "ITHZUJIWGRFARMW" +@test encrypt_solitaire("AAAAAAAAAAAAAAA", "a") == "XODALGSCULIQNSC" +@test encrypt_solitaire("AAAAAAAAAAAAAAA", "aa") == "OHGWMXXCAIMCIQP" +@test encrypt_solitaire("AAAAAAAAAAAAAAA", "aaa") == "DCSQYHBQZNGDRUT" +@test encrypt_solitaire("AAAAAAAAAAAAAAA", "b") == "XQEEMOITLZVDSQS" +@test encrypt_solitaire("AAAAAAAAAAAAAAA", "bc") == "QNGRKQIHCLGWSCE" +@test encrypt_solitaire("AAAAAAAAAAAAAAA", "bcd") == "FMUBYBMAXHNQXCJ" +@test encrypt_solitaire("AAAAAAAAAAAAAAAAAAAAAAAAA", "cryptonomicon") == "SUGSRSXSWQRMXOHIPBFPXARYQ" +@test encrypt_solitaire("SOLITAIREX", "cryptonomicon") == "KIRAKSFJAN" @test decrypt_solitaire("EXKYI ZSGEH UNTIQ", "") == "aaaaaaaaaaaaaaa" @test decrypt_solitaire("XYIUQ BMHKK JBEGY ", "f") == "aaaaaaaaaaaaaaa" diff --git a/test/vigenere.jl b/test/vigenere.jl index 3ec3c81..29f6f08 100644 --- a/test/vigenere.jl +++ b/test/vigenere.jl @@ -2,16 +2,15 @@ using ClassicalCiphers using Base.Test # doc examples -@test encrypt_vigenere("ab", [0, 1]) == "ac" +@test encrypt_vigenere("ab", [0, 1]) == "AC" @test decrypt_vigenere("ac", [0, 1]) == "ab" -@test encrypt_vigenere("ab", "ab") == "ac" +@test encrypt_vigenere("ab", "ab") == "AC" @test decrypt_vigenere("ac", "ab") == "ab" # others -@test decrypt_vigenere("DYIMXMESTEZDPNFVVAMJ", [11, 18, 5, 13, 12, 9, 14]-1) == lowercase("THEAMERICANSHAVEROBB") +@test decrypt_vigenere("DYIMXMESTEZDPNFVVAMJ", [11, 18, 5, 13, 12, 9, 14]-1) == "theamericanshaverobb" -@test decrypt_vigenere("DYIMXMESTEZDPNFVVAMJ", "kremlin") == lowercase("THEAMERICANSHAVEROBB") +@test decrypt_vigenere("DYIMXMESTEZDPNFVVAMJ", "kremlin") == "theamericanshaverobb" -@test encrypt_vigenere("THEAMERICANSHAVEROBB", "kremlin") == - lowercase("DYIMXMESTEZDPNFVVAMJ") \ No newline at end of file +@test encrypt_vigenere("THEAMERICANSHAVEROBB", "kremlin") == "DYIMXMESTEZDPNFVVAMJ"