From 2a0eb5c630feb438508f21faf68608ec072a418d Mon Sep 17 00:00:00 2001 From: Patrick Stevens Date: Thu, 12 Sep 2019 19:18:28 +0100 Subject: [PATCH] Move to Project.toml, bump to Julia v1 (#18) --- .gitignore | 2 ++ .travis.yml | 5 ++-- Project.toml | 15 +++++++++++ REQUIRE | 3 --- src/ClassicalCiphers.jl | 2 -- src/affine.jl | 32 ++++++++++++++++------- src/caesar.jl | 2 +- src/common.jl | 8 ++---- src/enigma.jl | 14 +++++----- src/hill.jl | 32 +++++++++-------------- src/monoalphabetic.jl | 2 +- src/playfair.jl | 13 +++++---- src/solitaire.jl | 58 ++++++++++++++++++++--------------------- src/vigenere.jl | 4 ++- test/affine.jl | 4 +-- test/caesar.jl | 2 +- test/enigma.jl | 2 +- test/hill.jl | 2 +- test/monoalphabetic.jl | 2 +- test/playfair.jl | 6 ++--- test/portas.jl | 2 +- test/runtests.jl | 15 ++++++++--- test/solitaire.jl | 2 +- test/vigenere.jl | 4 +-- 24 files changed, 128 insertions(+), 105 deletions(-) create mode 100644 Project.toml delete mode 100644 REQUIRE diff --git a/.gitignore b/.gitignore index 8c960ec..d0e30c2 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ *.jl.cov *.jl.*.cov *.jl.mem +Manifest.toml +.vscode/* diff --git a/.travis.yml b/.travis.yml index 408ae5b..d7dbed8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,10 +2,9 @@ language: julia os: - linux - - osx julia: - - 0.5 - - 0.6 + - 1.0 + - 1.1 - nightly notifications: email: false diff --git a/Project.toml b/Project.toml new file mode 100644 index 0000000..3c6b79e --- /dev/null +++ b/Project.toml @@ -0,0 +1,15 @@ +name = "ClassicalCiphers" +uuid = "ecf26e93-935c-5e64-9b21-bc8ac81b4723" + +[deps] +LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" +Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2" + +[compat] +julia = "≥ 1.0.0" + +[extras] +Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" + +[targets] +test = ["Test"] diff --git a/REQUIRE b/REQUIRE deleted file mode 100644 index bee7b97..0000000 --- a/REQUIRE +++ /dev/null @@ -1,3 +0,0 @@ -julia 0.5 -Compat 0.9.5 -Iterators diff --git a/src/ClassicalCiphers.jl b/src/ClassicalCiphers.jl index c26c3d5..c49ea39 100644 --- a/src/ClassicalCiphers.jl +++ b/src/ClassicalCiphers.jl @@ -2,8 +2,6 @@ module ClassicalCiphers # Monoalphabetic -using Compat - include("common.jl") include("monoalphabetic.jl") include("caesar.jl") diff --git a/src/affine.jl b/src/affine.jl index b259b19..f1cfd57 100644 --- a/src/affine.jl +++ b/src/affine.jl @@ -1,5 +1,3 @@ -using Iterators - """ Encrypts the given plaintext according to the Affine cipher. The key is given as a pair of integers: first the multiplier, then @@ -42,6 +40,26 @@ function decrypt_affine(ciphertext, mult::Integer, add::Integer; offset=0) decrypt_monoalphabetic(ciphertext, keystr) end +function max_by(arr, f) + currMax = undef + currAns = undef + set = false + for i in arr + if set == false + set = true + currMax = f(i) + currAns = i + else + t = f(i) + if currMax < t + currMax = t + currAns = i + end + end + end + currAns +end + """ Cracks the given ciphertext according to the Affine cipher. Returns ((multiplier, additive constant), decrypted string). @@ -51,15 +69,11 @@ Converts the input to lowercase, but retains symbols. Optional arguments: mult=0, which specifies the multiplier if known; add=-1, which specifies the additive constant if known. """ -function crack_affine(ciphertext; mult=0, add=-1) +function crack_affine(ciphertext::AbstractString; mult=0, add=-1) mults = mult != 0 ? [mult] : [i for i in filter(x -> (x % 2 != 0 && x % 13 != 0), 1:25)] adds = add != -1 ? [add] : (0:25) - possible_keys = product(mults, adds) + possible_keys = Iterators.product(mults, adds) - decrypts = [(i, decrypt_affine(ciphertext, i[1], i[2])) for i in possible_keys] - - sort!(decrypts, by=(x -> string_fitness(x[2]))) - - reverse(decrypts[end]) + reverse(max_by([(i, decrypt_affine(ciphertext, i[1], i[2])) for i in possible_keys], x -> string_fitness(x[2]))) end \ No newline at end of file diff --git a/src/caesar.jl b/src/caesar.jl index 1aeac3c..dc3f6c4 100644 --- a/src/caesar.jl +++ b/src/caesar.jl @@ -5,7 +5,7 @@ so encrypt_caesar("abc", 1) == "BCD". Converts the input to uppercase. """ -function encrypt_caesar(plaintext, key::Integer) +function encrypt_caesar(plaintext, key::T) where {T<:Integer} # plaintext: string; key: integer offset, so k=1 sends "a" to "b" key = ((key-1) % 26) + 1 keystr = join([collect(Char(97+key):'z'); collect('a':Char(97+key-1))]) diff --git a/src/common.jl b/src/common.jl index b4d6507..f34f6eb 100644 --- a/src/common.jl +++ b/src/common.jl @@ -29,10 +29,6 @@ function rotateRightStr(st::AbstractString, n) join(rotateRight(split(st, ""), n), "") end -flatten{T}(a::Array{T,1}) = any(x->isa(x,Array),a)? flatten(vcat(map(flatten,a)...)): a -flatten{T}(a::Array{T}) = reshape(a,prod(size(a))) -flatten(a)=a - function splitBy(arr, func) # implementation of the Mathematica function SplitBy # splits the array into sublists so that each list has the same value of func @@ -58,7 +54,7 @@ function get_trigram_fitnesses() for l in lines (ngram, fitness) = split(l) - dict[ngram] = parse(fitness) + dict[ngram] = parse(Int32, fitness) end close(f) @@ -72,7 +68,7 @@ Performs a trigram analysis on the input string, to determine how close it is to English. That is, splits the input string into groups of three letters, and assigns a score based on the frequency of the trigrams in true English. """ -function string_fitness(input; alreadystripped=false) +function string_fitness(input::AbstractString; alreadystripped=false) if !alreadystripped str = letters_only(input) else diff --git a/src/enigma.jl b/src/enigma.jl index 86e1090..dc1d627 100644 --- a/src/enigma.jl +++ b/src/enigma.jl @@ -59,7 +59,7 @@ Arguments are in the order: plaintext, stecker, rotors, ring, key. Plaintext is a string; punctuation is stripped out and it is made lowercase. Rotors is an array - for example, [1,2,3] - being the order of the rotors. - Each entry should be a distinct integer between 1 and 5 inclusive. + Each entry should be a distinct integer between 1 and 5 inclusive. Key is a string of three letters, indicating the starting positions of the rotors. Optional: @@ -72,15 +72,15 @@ Ring is a string - for example, "AAA" - being the offset applied to each rotor. "AAA", for example, signifies no offset. The string must be three letters. skip_stecker_check=false, which when `true` skips validation of stecker settings. """ -function encrypt_enigma{I <: Integer}(plaintext, - rotors::Array{I, 1}, key::AbstractString; - reflector_id='B', ring::AbstractString = "AAA", - stecker = Tuple{Char, Char}[], - skip_stecker_check = false) +function encrypt_enigma(plaintext, + rotors::Array{T, 1}, key::AbstractString; + reflector_id='B', ring::AbstractString = "AAA", + stecker = Tuple{Char, Char}[], + skip_stecker_check = false) where {T<:Integer} parsed_stecker = parse_stecker(stecker) # validate stecker settings if !skip_stecker_check - if flatten(parsed_stecker) != unique(flatten(parsed_stecker)) + if collect(Iterators.flatten(parsed_stecker)) != collect(unique(Iterators.flatten(parsed_stecker))) error("No letter may appear more than once in stecker settings.") end end diff --git a/src/hill.jl b/src/hill.jl index fa741b4..91a2479 100644 --- a/src/hill.jl +++ b/src/hill.jl @@ -1,4 +1,4 @@ -using Iterators +using LinearAlgebra """ Encrypts the given plaintext according to the Hill cipher. @@ -12,7 +12,7 @@ is thrown. The matrix must be invertible modulo 26. If it is not, an error is thrown. """ -function encrypt_hill{I <: Integer}(plaintext, key::Array{I, 2}) +function encrypt_hill(plaintext::AbstractString, key::AbstractArray{T, 2}) where {T<:Integer} if round(Integer, det(key)) % 26 == 0 error("Key must be invertible mod 26.") end @@ -30,7 +30,7 @@ function encrypt_hill{I <: Integer}(plaintext, key::Array{I, 2}) # split split_text = reshape(chars, (keysize, div(length(text), keysize))) - encrypted = mapslices(group -> 65 .+ ((key * group) .% 26), split_text, 1) + encrypted = mapslices(group -> 65 .+ ((key * group) .% 26), split_text, dims = [1]) ans = IOBuffer() for group in encrypted @@ -42,24 +42,21 @@ function encrypt_hill{I <: Integer}(plaintext, key::Array{I, 2}) end -function encrypt_hill(plaintext, key::AbstractString) +function encrypt_hill(plaintext::AbstractString, key::AbstractString) if round(Integer, sqrt(length(key))) != sqrt(length(key)) error("Hill key must be of square integer size.") end matrix_dim = round(Integer, sqrt(length(key))) - key_string = uppercase(letters_only(key)) + keys = map(x -> Int(x) - 65, collect(uppercase(letters_only(key)))) - key_matrix = Array{Integer}(matrix_dim, matrix_dim) - for i in 1:length(key) - key_matrix[ind2sub([matrix_dim, matrix_dim], i)...] = Int(key_string[i]) - 65 - end + key_matrix = reshape(keys, matrix_dim, matrix_dim) encrypt_hill(plaintext, transpose(key_matrix)) end -function minor{I <: Integer}(mat::Array{I, 2}, i, j) +function minor(mat::AbstractArray{T, 2}, i, j) where {T<:Integer} d = det(mat[[1:i-1; i+1:end], [1:j-1; j+1:end]]) round(Integer, d) end @@ -67,13 +64,13 @@ end """ Computes the adjugate matrix for given matrix. """ -function adjugate{I <: Integer}(mat::Array{I, 2}) - arr = [(-1)^(i+j) * minor(mat, i, j) for (i, j) in product(1:size(mat, 1), 1:size(mat, 2))] +function adjugate(mat::AbstractArray{T, 2}) where {T<:Integer} + arr = [(-1)^(i+j) * minor(mat, i, j) for (i, j) in Iterators.product(1:size(mat, 1), 1:size(mat, 2))] ans = reshape(arr, size(mat)) Array{Integer, 2}(transpose(ans)) end -function decrypt_hill{I <: Integer}(ciphertext, key::Array{I, 2}) +function decrypt_hill(ciphertext, key::AbstractArray{T, 2}) where {T<:Integer} if ndims(key) != 2 error("Key must be a two-dimensional matrix.") end @@ -97,12 +94,9 @@ function decrypt_hill(ciphertext, key::AbstractString) end matrix_dim = round(Integer, sqrt(length(key))) - key_string = uppercase(letters_only(key)) + keys = map(x -> Int(x) - 65, collect(uppercase(letters_only(key)))) + + key_matrix = reshape(keys, matrix_dim, matrix_dim) - key_matrix = Array{Integer}(matrix_dim, matrix_dim) - for i in 1:length(key) - key_matrix[ind2sub([matrix_dim, matrix_dim], i)...] = Int(key_string[i]) - 65 - end - decrypt_hill(ciphertext, transpose(key_matrix)) end \ No newline at end of file diff --git a/src/monoalphabetic.jl b/src/monoalphabetic.jl index d84fcd1..2d72d5e 100644 --- a/src/monoalphabetic.jl +++ b/src/monoalphabetic.jl @@ -47,7 +47,7 @@ function decrypt_monoalphabetic(ciphertext, key::AbstractString) # working in lowercase; key is assumed only to have each element appearing once # and to be in lowercase # so decrypt_monoalphabetic("cb", "cbade…") is "ab" - dict = Dict(a => Char(96 + search(lowercase(key), a)) for a in lowercase(key)) + dict = Dict(a => Char(96 + findfirst(i -> i == a, lowercase(key))) for a in lowercase(key)) encrypt_monoalphabetic(lowercase(ciphertext), dict) end diff --git a/src/playfair.jl b/src/playfair.jl index d3fc647..94222dd 100644 --- a/src/playfair.jl +++ b/src/playfair.jl @@ -11,8 +11,8 @@ function playfair_key_to_square(key::AbstractString, replacement) # delete duplicates etc from key key_sanitised = union(uppercase(letters_only(key))) # construct key square - remaining = collect(filter(x -> (x != replacement[2] && findfirst(key_sanitised, x) == 0), 'A':'Z')) - keysquare = reshape([key_sanitised; remaining], 5, 5) + remaining = filter(x -> (x != replacement[2] && !(in(x, key_sanitised))), 'A':'Z') + keysquare = reshape(collect(Iterators.flatten([key_sanitised; remaining])), 5, 5) return permutedims(keysquare, (2, 1)) # transpose() is deprecated end @@ -39,7 +39,7 @@ combined=('I', 'J'), marks the characters which are to be combined in the text. """ function encrypt_playfair(plaintext, key::Array{Char, 2}; stripped=false, combined=('I', 'J')) if !stripped - if findfirst(key, combined[2]) != 0 + if in(combined[2], key) error("Key must not contain symbol $(combined[2]), as it was specified to be combined.") end plaintext_sanitised = uppercase(letters_only(plaintext)) @@ -88,8 +88,8 @@ function encrypt_playfair(plaintext, key::Array{Char, 2}; stripped=false, combin l1 = plaintext_sanitised[i] l2 = plaintext_sanitised[i+1] - l1pos = ind2sub((5, 5), findfirst(key, l1)) - l2pos = ind2sub((5, 5), findfirst(key, l2)) + l1pos = CartesianIndices((5, 5))[findfirst(i -> i == l1, key)] + l2pos = CartesianIndices((5, 5))[findfirst(i -> i == l2, key)] @assert l1pos != l2pos @@ -124,7 +124,6 @@ Does not attempt to delete X's inserted as padding for double letters. """ function decrypt_playfair(ciphertext, key::Array{Char, 2}; combined=('I', 'J')) # to obtain the decrypting keysquare, reverse every row and every column - keysquare = mapslices(reverse, key, 2) - keysquare = permutedims(mapslices(reverse, permutedims(keysquare, (2, 1)), 2), (2, 1)) + keysquare = reverse(reverse(key, dims=1), dims=2) lowercase(encrypt_playfair(ciphertext, keysquare, combined=combined)) end diff --git a/src/solitaire.jl b/src/solitaire.jl index a5fb810..f125224 100644 --- a/src/solitaire.jl +++ b/src/solitaire.jl @@ -1,8 +1,8 @@ -function next_solitaire(deckIn) +function next_solitaire(deckIn::AbstractVector{T}) :: AbstractVector{Integer} where {T<:Integer} # performs one round of Solitaire on the given deck # first joker deck = deckIn - jokerPos = findin(deck, 53)[1] + jokerPos = findfirst(i -> i == 53, deck) if jokerPos != length(deck) inter = deck[jokerPos+1] deck[jokerPos+1] = deck[jokerPos] @@ -14,7 +14,7 @@ function next_solitaire(deckIn) deck = rotateRight(deck) end # second joker - jokerPos = findin(deck, 54)[1] + jokerPos = findfirst(i -> i == 54, deck) if jokerPos <= length(deck) - 2 inter = deck[jokerPos] deck[jokerPos] = deck[jokerPos+1] @@ -49,7 +49,7 @@ function next_solitaire(deckIn) split_deck[1] = split_deck[end] split_deck[end] = inter end - deck = flatten(split_deck) + deck = collect(Iterators.flatten(split_deck)) # take bottom of deck and put it just above last card cardsToTake = (deck[end] > 52) ? 0 : deck[end] @@ -57,28 +57,34 @@ function next_solitaire(deckIn) append!(intermediate, [deck[end]]) deck = intermediate - return deck + return collect(deck) end -function keychar_from_deck(deck::Vector) +function keychar_from_deck(deck::AbstractVector{T}) :: Integer where {T<:Integer} # given a deck, returns an integer which is the Solitaire key value # output by that deck deck[((deck[1]==54 ? 53 : deck[1]) % length(deck)) + 1] end -type SolitaireKeyStream - deck::Vector +struct SolitaireKeyStreamStruct + deck::AbstractVector{Integer} end -Base.start(b::SolitaireKeyStream) = (next_solitaire(b.deck)) -function Base.next(b::SolitaireKeyStream, state) - curState = state +function Base.iterate(b::SolitaireKeyStreamStruct) + (0, next_solitaire(b.deck)) +end + +function Base.iterate(b::SolitaireKeyStreamStruct, state) + curState = state::AbstractVector{Integer} while keychar_from_deck(curState) > 52 curState = next_solitaire(curState) end - (keychar_from_deck(curState), next_solitaire(curState)) + (keychar_from_deck(curState)::Integer, next_solitaire(curState)) +end + +function SolitaireKeyStream(initialDeck::AbstractVector{T}) where {T<:Integer} + Iterators.filter(i -> i <= 52, Iterators.drop(SolitaireKeyStreamStruct(initialDeck), 1)) end -Base.done(b::SolitaireKeyStream, state) = false """ Encrypts the given plaintext according to the Solitaire cipher. @@ -86,16 +92,11 @@ The key may be given either as a vector initial deck, where the cards are 1 through 54 (the two jokers being 53, 54), or as a string. Schneier's keying algorithm is used to key the deck if the key is a string. """ -function encrypt_solitaire(string, initialDeck::Vector) +function encrypt_solitaire(string, initialDeck::AbstractVector{T}) :: AbstractString where {T<:Integer} inp = uppercase(letters_only(string)) ans = "" - i = 0 - for keyval in SolitaireKeyStream(initialDeck) - i += 1 - if i > length(inp) - break - end - ans *= encrypt_caesar(inp[i], keyval) + for (keyval::Integer, input::Char) in zip(SolitaireKeyStream(initialDeck), collect(inp)) + ans *= encrypt_caesar(input, keyval) end return ans end @@ -110,17 +111,13 @@ function decrypt_solitaire(string, initialDeck::Vector) inp = uppercase(letters_only(string)) ans = "" i = 0 - for keyval in SolitaireKeyStream(initialDeck) - i += 1 - if i > length(inp) - break - end - ans *= decrypt_caesar(inp[i], keyval) + for (keyval, input) in zip(SolitaireKeyStream(initialDeck), collect(inp)) + ans *= decrypt_caesar(input, keyval) end return ans end -function key_deck(key::AbstractString) +function key_deck(key::AbstractString) :: AbstractVector{Integer} # returns the Solitaire deck after it has been keyed with the given string deck = collect(1:54) for keyval in uppercase(letters_only(key)) @@ -133,8 +130,9 @@ function key_deck(key::AbstractString) deck end -function encrypt_solitaire(string, key::AbstractString) - encrypt_solitaire(string, key_deck(key)) +function encrypt_solitaire(string::AbstractString, key::AbstractString) :: AbstractString + key = key_deck(key) + encrypt_solitaire(string, key) end function decrypt_solitaire(string, key::AbstractString) diff --git a/src/vigenere.jl b/src/vigenere.jl index d491904..36bc45a 100644 --- a/src/vigenere.jl +++ b/src/vigenere.jl @@ -1,3 +1,5 @@ +using Statistics + """ Encrypts the given string using the Vigenere cipher according to the given vector of offsets. For example, encrypt_vigenere("ab", [0, 1]) returns "AC". @@ -14,7 +16,7 @@ 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" - lowercase(encrypt_vigenere(ciphertext, 26-key)) + lowercase(encrypt_vigenere(ciphertext, map(x -> 26-x, key))) end """ diff --git a/test/affine.jl b/test/affine.jl index e2edb15..006f462 100644 --- a/test/affine.jl +++ b/test/affine.jl @@ -1,10 +1,10 @@ using ClassicalCiphers -using Base.Test +using Test # docs examples @test encrypt_affine("Hello, World!", 3, 4) == "ZQLLU, SUDLN!" -@test decrypt_affine("ZQLLU, SUDLN!", 3, 4) == "hello, world!" +@test decrypt_affine("ZQLLU, SUDLN!", 3, 4) == "hello, world!" @test crack_affine("zqllu, sudln!") == ("hello, world!", (3, 4)) # Wikipedia examples diff --git a/test/caesar.jl b/test/caesar.jl index b4dc916..e3d3b1d 100644 --- a/test/caesar.jl +++ b/test/caesar.jl @@ -1,5 +1,5 @@ using ClassicalCiphers -using Base.Test +using Test @test encrypt_caesar("THIS CODE WAS INVENTED BY JULIUS CAESAR", 3) == "WKLV FRGH ZDV LQYHQWHG EB MXOLXV FDHVDU" diff --git a/test/enigma.jl b/test/enigma.jl index 01a8f1e..331a9d5 100644 --- a/test/enigma.jl +++ b/test/enigma.jl @@ -1,5 +1,5 @@ using ClassicalCiphers -using Base.Test +using Test @test (encrypt_enigma("AAA", [1,2,3], "AAA") == "BDZ") @test (decrypt_enigma("BDZ", [1,2,3], "AAA") == "aaa") diff --git a/test/hill.jl b/test/hill.jl index 8bdd635..04d1f2c 100644 --- a/test/hill.jl +++ b/test/hill.jl @@ -1,5 +1,5 @@ using ClassicalCiphers -using Base.Test +using Test # Wikipedia examples diff --git a/test/monoalphabetic.jl b/test/monoalphabetic.jl index 3054b7d..58a4a2a 100644 --- a/test/monoalphabetic.jl +++ b/test/monoalphabetic.jl @@ -1,5 +1,5 @@ using ClassicalCiphers -using Base.Test +using Test @test encrypt_monoalphabetic("aBcbD", Dict{Char, Char}('a' => '5', 'B' => '@', 'b' => 'o', 'D' => 'D')) == "5@coD" diff --git a/test/playfair.jl b/test/playfair.jl index 7e49205..98a36d1 100644 --- a/test/playfair.jl +++ b/test/playfair.jl @@ -1,5 +1,5 @@ using ClassicalCiphers -using Base.Test +using Test # Wikipedia example @test encrypt_playfair("Hide the gold in the tree stump", "playfair example") == "BMODZBXDNABEKUDMUIXMMOUVIF" @@ -9,7 +9,7 @@ using Base.Test # doc examples @test encrypt_playfair("Hello, World!", "playfair example") == "DMYRANVQCRGE" -@test (arr = ['P' 'L' 'A' 'Y' 'F'; 'I' 'R' 'E' 'X' 'M'; 'B' 'C' 'D' 'G' 'H'; 'K' 'N' 'O' 'Q' 'S'; 'T' 'U' 'V' 'W' 'Z']; +@test (arr = ['P' 'L' 'A' 'Y' 'F'; 'I' 'R' 'E' 'X' 'M'; 'B' 'C' 'D' 'G' 'H'; 'K' 'N' 'O' 'Q' 'S'; 'T' 'U' 'V' 'W' 'Z']; encrypt_playfair("Hello, World!", arr) == "DMYRANVQCRGE") @test encrypt_playfair("HELXLOWORLD", "PLAYFIREXM") == "DMYRANVQCRGE" @@ -20,7 +20,7 @@ using Base.Test @test decrypt_playfair("BSGXEY", "PLAYFIREXM", combined=('X', 'Z')) == "ijxyxa" @test decrypt_playfair("RMRMFWYE", "PLAYFIREXM", combined=('I', 'J')) == "ixixyzax" @test decrypt_playfair("DMYRANVQCRGE", "playfair example") == "helxloworldx" -@test (arr = ['P' 'L' 'A' 'Y' 'F'; 'I' 'R' 'E' 'X' 'M'; 'B' 'C' 'D' 'G' 'H'; 'K' 'N' 'O' 'Q' 'S'; 'T' 'U' 'V' 'W' 'Z']; +@test (arr = ['P' 'L' 'A' 'Y' 'F'; 'I' 'R' 'E' 'X' 'M'; 'B' 'C' 'D' 'G' 'H'; 'K' 'N' 'O' 'Q' 'S'; 'T' 'U' 'V' 'W' 'Z']; decrypt_playfair("DMYRANVQCRGE", arr) == "helxloworldx") @test decrypt_playfair("GDDOGDRQARKYGDHDNKPRDAMSOGUPGKICQY", "charles") == "meetmeathamxmersmithbridgetonightx" @test decrypt_playfair("BMODZBXDNABEKUDMUIXMMOUVIF", "playfair example") == "hidethegoldinthetrexestump" \ No newline at end of file diff --git a/test/portas.jl b/test/portas.jl index 4a60897..6cbd634 100644 --- a/test/portas.jl +++ b/test/portas.jl @@ -1,5 +1,5 @@ using ClassicalCiphers -using Base.Test +using Test @test encrypt_portas("DEFENDTHEEASTWALLOFTHECASTLE", "FORTIFICATION") == uppercase("synnjscvrnrlahutukucvryrlany") @test decrypt_portas("synnjscvrnrlahutukucvryrlany", "FORTIFICATION") == lowercase("DEFENDTHEEASTWALLOFTHECASTLE") diff --git a/test/runtests.jl b/test/runtests.jl index 1afa521..a3c3a1f 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -1,8 +1,17 @@ using ClassicalCiphers +using Test -tests = ["vigenere", "monoalphabetic", "solitaire", - "caesar", "portas", "affine", "hill", "playfair", - "enigma"] +tests = [ + "playfair", + "vigenere", + "monoalphabetic", + "caesar", + "portas", + "affine", + "enigma", + "hill", + "solitaire", + ] println("Running tests:") diff --git a/test/solitaire.jl b/test/solitaire.jl index 98b8251..1d5999b 100644 --- a/test/solitaire.jl +++ b/test/solitaire.jl @@ -1,5 +1,5 @@ using ClassicalCiphers -using Base.Test +using Test @test encrypt_solitaire("aaaaaaaaaaaaaaa", "") == "EXKYIZSGEHUNTIQ" @test encrypt_solitaire("aaaaaaaaaaaaaaa", "f") == "XYIUQBMHKKJBEGY" diff --git a/test/vigenere.jl b/test/vigenere.jl index beb8f65..bd40cd1 100644 --- a/test/vigenere.jl +++ b/test/vigenere.jl @@ -1,5 +1,5 @@ using ClassicalCiphers -using Base.Test +using Test # doc examples @test encrypt_vigenere("ab", [0, 1]) == "AC" @@ -9,7 +9,7 @@ using Base.Test # others -@test decrypt_vigenere("DYIMXMESTEZDPNFVVAMJ", [11, 18, 5, 13, 12, 9, 14]-1) == "theamericanshaverobb" +@test decrypt_vigenere("DYIMXMESTEZDPNFVVAMJ", map(x -> x - 1, [11, 18, 5, 13, 12, 9, 14])) == "theamericanshaverobb" @test decrypt_vigenere("DYIMXMESTEZDPNFVVAMJ", "kremlin") == "theamericanshaverobb"