Playfair cipher

You are encouraged to solve this task according to the task description, using any language you may know.
Task

Implement a  Playfair cipher for encryption and decryption.



The user must be able to choose   J  =  I     or   no   Q   in the alphabet.

The output of the encrypted and decrypted message must be in capitalized digraphs, separated by spaces.



Output example

                HI DE TH EG OL DI NT HE TR EX ES TU MP



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))
 