mirror of
https://github.com/Smaug123/ClassicalCiphers.jl
synced 2025-10-05 17:38:48 +00:00
Added Rail Fence Cipher implementation (addresses #23)
This is only my attempt at an implementation. @r0cketr1kky can still have another attempt, or refine my solution, but it is here now for people to use. TODO: add better docstrings.
This commit is contained in:
@@ -12,6 +12,7 @@ include("affine.jl")
|
||||
include("hill.jl")
|
||||
include("playfair.jl")
|
||||
include("enigma.jl")
|
||||
include("railfence.jl")
|
||||
|
||||
export encrypt_monoalphabetic, decrypt_monoalphabetic, crack_monoalphabetic,
|
||||
encrypt_caesar, decrypt_caesar, crack_caesar,
|
||||
@@ -22,6 +23,7 @@ export encrypt_monoalphabetic, decrypt_monoalphabetic, crack_monoalphabetic,
|
||||
encrypt_hill, decrypt_hill,
|
||||
encrypt_playfair, decrypt_playfair,
|
||||
encrypt_enigma, decrypt_enigma,
|
||||
string_fitness, index_of_coincidence
|
||||
string_fitness, index_of_coincidence,
|
||||
construct_railfence, encrypt_railfence, decrypt_railfence
|
||||
|
||||
end # module
|
||||
|
49
src/railfence.jl
Normal file
49
src/railfence.jl
Normal file
@@ -0,0 +1,49 @@
|
||||
function construct_railfence(input, fence::AbstractArray, n_rails::Integer)
|
||||
rails = vcat(1:n_rails, (n_rails - 1):-1:2)
|
||||
|
||||
for (i, letter) in enumerate(input)
|
||||
fence[rails[mod1(i, length(rails))], i] = letter
|
||||
end
|
||||
|
||||
return fence
|
||||
end
|
||||
|
||||
"""
|
||||
```julia
|
||||
construct_railfence(input::AbstractString, n_rails::Integer)
|
||||
construct_railfence(input::AbstractArray{T}, n_rails::Integer) where {T <: Number}
|
||||
```
|
||||
|
||||
See https://en.wikipedia.org/wiki/Rail_fence_cipher.
|
||||
"""
|
||||
function construct_railfence(input::AbstractString, n_rails::Integer)
|
||||
input = uppercase(replace(input, " " => ""))
|
||||
# the square is my `UndefInitializer()` for `Char`.
|
||||
return construct_railfence(input, fill('□', n_rails, length(input)), n_rails)
|
||||
end
|
||||
function construct_railfence(input::AbstractArray{T}, n_rails::Integer) where {T <: Number}
|
||||
return construct_railfence(input, zeros(T, n_rails, length(input)), n_rails)
|
||||
end
|
||||
|
||||
"""
|
||||
```julia
|
||||
encrypt_railfence(input::AbstractString, n_rails::Integer)
|
||||
```
|
||||
|
||||
See https://en.wikipedia.org/wiki/Rail_fence_cipher.
|
||||
"""
|
||||
function encrypt_railfence(input::AbstractString, n_rails::Integer)
|
||||
return join(Char[c for rail in eachrow(construct_railfence(input, n_rails)) for c in rail if c != '□'])
|
||||
end
|
||||
|
||||
"""
|
||||
```julia
|
||||
encrypt_railfence(input::AbstractString, n_rails::Integer)
|
||||
```
|
||||
|
||||
See https://en.wikipedia.org/wiki/Rail_fence_cipher.
|
||||
"""
|
||||
function decrypt_railfence(input::AbstractString, n_rails::Integer)
|
||||
char_positions = Int[n for row in eachrow(construct_railfence(1:length(input), n_rails)) for n in row if n != 0]
|
||||
return lowercase(join(Char[input[findfirst(==(i), char_positions)] for i in 1:length(input)]))
|
||||
end
|
10
test/railfence.jl
Normal file
10
test/railfence.jl
Normal file
@@ -0,0 +1,10 @@
|
||||
# using ClassicalCiphers
|
||||
# using Test
|
||||
|
||||
@test encrypt_railfence("WE ARE DISCOVERED. FLEE AT ONCE", 3) == "WECRFACERDSOEE.LETNEAIVDEO"
|
||||
@test decrypt_railfence("WECRFACERDSOEE.LETNEAIVDEO", 3) == "wearediscovered.fleeatonce"
|
||||
@test encrypt_railfence("Julia is strong", 10) == "JULIAISGSNTOR"
|
||||
@test decrypt_railfence("JULIAISGSNTOR", 10) == "juliaisstrong"
|
||||
@test encrypt_railfence("This is not a very strong cipher, but indeed it is classical", 2) == "TIINTVRSRNCPE,UIDEIICASCLHSSOAEYTOGIHRBTNEDTSLSIA"
|
||||
@test decrypt_railfence("TIINTVRSRNCPE,UIDEIICASCLHSSOAEYTOGIHRBTNEDTSLSIA", 2) == "thisisnotaverystrongcipher,butindeeditisclassical"
|
||||
@test construct_railfence("WE ARE DISCOVERED. FLEE AT ONCE", 3) == ['W' '□' '□' '□' 'E' '□' '□' '□' 'C' '□' '□' '□' 'R' '□' '□' '□' 'F' '□' '□' '□' 'A' '□' '□' '□' 'C' '□'; '□' 'E' '□' 'R' '□' 'D' '□' 'S' '□' 'O' '□' 'E' '□' 'E' '□' '.' '□' 'L' '□' 'E' '□' 'T' '□' 'N' '□' 'E'; '□' '□' 'A' '□' '□' '□' 'I' '□' '□' '□' 'V' '□' '□' '□' 'D' '□' '□' '□' 'E' '□' '□' '□' 'O' '□' '□' '□']
|
@@ -11,6 +11,7 @@ tests = [
|
||||
"enigma",
|
||||
"hill",
|
||||
"solitaire",
|
||||
"railfence"
|
||||
]
|
||||
|
||||
println("Running tests:")
|
||||
|
Reference in New Issue
Block a user