RosettaCodeData/Task/Playfair-cipher/Julia/playfair-cipher.julia
2023-07-01 13:44:08 -04:00

60 lines
1.9 KiB
Text

function playfair(key, txt, isencode=true, from = "J", to = "")
to = (to == "" && from == "J") ? "I" : to
function canonical(s, dup_toX=true)
s = replace(replace(uppercase(s), from => to), r"[^A-Z]" => "")
a, dupcount = [c for c in s], 0
for i in 1:2:length(a)-1
if s[i] == s[i + 1]
dup_toX && splice!(a, i+1+dupcount:i+dupcount, 'X')
dupcount += 1
end
end
s = String(a)
return isodd(length(s)) ? s * "X" : s
end
# Translate key into an encoding 5x5 translation matrix.
keyletters = unique([c for c in canonical(key * "ABCDEFGHIJKLMNOPQRSTUVWXYZ", false)])
m = Char.((reshape(UInt8.(keyletters[1:25]), 5, 5)'))
# encod is a dictionary of letter pairs for encoding.
encod = Dict()
# Map pairs in same row or same column of matrix m.
for i in 1:5, j in 1:5, k in 1:5
if j != k
encod[m[i, j] * m[i, k]] = m[i, mod1(j + 1, 5)] * m[i, mod1(k + 1, 5)]
end
if i != k
encod[m[i, j] * m[k, j]] = m[mod1(i + 1, 5), j] * m[mod1(k + 1, 5), j]
end
# Map pairs not on same row or same column.
for l in 1:5
if i != k && j != l
encod[m[i, j] * m[k, l]] = m[i, l] * m[k, j]
end
end
end
# Get array of pairs of letters from text.
canontxt = canonical(txt)
letterpairs = [canontxt[i:i+1] for i in 1:2:length(canontxt)-1]
if isencode
# Encode text
return join([encod[pair] for pair in letterpairs], " ")
else
# Decode text
decod = Dict((v, k) for (k, v) in encod)
return join([decod[pair] for pair in letterpairs], " ")
end
end
orig = "Hide the gold in...the TREESTUMP!!!"
println("Original: ", orig)
encoded = playfair("Playfair example", orig)
println("Encoded: ", encoded)
println("Decoded: ", playfair("Playfair example", encoded, false))