## Bifid Cipher

### October 13, 2009

The bifid cipher was invented by the French cryptographer Felix Delastelle in 1901. Though never used militarily, it is popular among classical cryptographers because it is simple to operate manually yet reasonably secure. Bifid uses a Polybius square to substitute a digit-pair for each plain-text letter, then transposition causes fractionation of the digit pairs, creating diffusion, and finally the transposed digits are reformed into cipher-text letters. An example is shown below:

```  1 2 3 4 5 1 A B C D E 2 F G H I K 3 L M N O P 4 Q R S T U 5 V W X Y Z```

Our “key” is just the letters of the alphabet, in order, with J omitted; other methods of building a Polybius square have been discussed in previous exercises. To encipher a message, write the row and column numbers of the letters in two rows below the message:

```P R O G R A M M I N G P R A X I S 3 4 3 2 4 1 3 3 2 3 2 3 4 1 5 2 4 5 2 4 2 2 1 2 2 4 3 2 5 2 1 3 4 3```

Then the digits are read off by rows, in pairs, and converted back to letters:

```34 32 41 33 23 23 41 52 45 24 22 12 24 32 52 13 43 O  M  Q  N  H  H  Q  W  U  I  G  B  I  M  W  C  S```

So the cipher-text is OMQNHHQWUIGBIMWCS. Deciphering is the inverse operation.

Some variants of bifid break the plain-text into blocks of a given length, called the period, before encipherment, then encipher each block separately; a common period is five. A 6 × 6 variant that includes digits is also common. Another variant of bifid, called trifid, uses a 3 × 3 × 3 cube instead of a square, on the theory that if fractionating by two is good, fractionating by three is better.

Your task is to write functions that encipher and decipher messages using the bifid cipher. When you are finished, you are welcome to read or run a suggested solution, or to post your solution or discuss the exercise in the comments below.

Pages: 1 2

### 22 Responses to “Bifid Cipher”

1. Remco Niemeijer said

```import Data.Char
import Data.List
import Data.List.HT hiding (unzip)
import Data.Map ((!), fromList)

alphabet :: String
alphabet = delete 'J' ['A'..'Z']

indices :: [(Int, Int)]
indices = zip (concatMap (replicate 5) [1..5]) (cycle [1..5])

toIndex :: Char -> (Int, Int)
toIndex c = fromList (zip alphabet indices) ! c

fromIndex :: [Int] -> Char
fromIndex [x, y] = fromList (zip indices alphabet) ! (x, y)
fromIndex _      = undefined

prepare :: String -> String
prepare = filter (`elem` alphabet) . replace "J" "I" . map toUpper

encode :: String -> String
encode = map fromIndex . sliceVertical 2 . uncurry (++) .
unzip . map toIndex . prepare

decode :: String -> String
decode xs = map fromIndex . sliceHorizontal (length xs) .
concatMap ((\(x, y) -> [x, y]) . toIndex) \$ prepare xs
```
2. liesen said

import Data.Char
import Data.List
import Data.Maybe (fromJust)

alphabet = delete ‘J’ [‘A’..’Z’]

normalize = filter (`elem` alphabet) . replace1 ‘J’ ‘I’ . map toUpper
where
replace1 _ _ [] = []
replace1 x y (z:zs) = (if x == z then y else z) : replace1 x y zs

encode1 :: (Int, Int) -> Char
encode1 = fromJust . flip lookup ((map (`divMod` 5) [0..]) `zip` alphabet)

decode1 :: Char -> (Int, Int)
decode1 = fromJust . flip lookup (alphabet `zip` (map (`divMod` 5) [0..]))

encode, decode :: String -> String
encode = map encode1 . pair . uncurry (++) . unzip . map decode1 . normalize
where
pair (x:y:zs) = (x, y) : pair zs
pair _ = []

decode s = map encode1 \$ uncurry zip
\$ splitAt n
\$ foldr (\(x, y) zs -> x : y : zs) []
\$ map decode1
\$ normalize s
where
n = length s

I need to check out Data.List.HT.

3. […] Praxis – Bifid Cipher By Remco Niemeijer Today’s Programming Praxis problem is another cipher, specifically Bifid’s cipher. Let’s get […]

4. Well here’s my t-sql version

CREATE FUNCTION [dbo].[DeEnCrypt]
(
— Add the parameters for the function here
@string nvarchar(max), @bit bit
)
RETURNS nvarchar(max)
AS
BEGIN
— Declare the return variable here

declare @table table (y char(1), x char(1), Chr char(1))
declare @i int,
@count int,
@x nvarchar(max), –holds x coordinate
@y nvarchar(max), –holds y coordinate
@catnum nvarchar(max), –concatinated x and y coordinates
@cat nvarchar(max) –end result

insert into @table values (1,1,’A’)
insert into @table values (1,2,’B’)
insert into @table values (1,3,’C’)
insert into @table values (1,4,’D’)
insert into @table values (1,5,’E’)
insert into @table values (2,1,’F’)
insert into @table values (2,2,’G’)
insert into @table values (2,3,’H’)
insert into @table values (2,4,’I’)
insert into @table values (2,5,’K’)
insert into @table values (3,1,’L’)
insert into @table values (3,2,’M’)
insert into @table values (3,3,’N’)
insert into @table values (3,4,’O’)
insert into @table values (3,5,’P’)
insert into @table values (4,1,’Q’)
insert into @table values (4,2,’R’)
insert into @table values (4,3,’S’)
insert into @table values (4,4,’T’)
insert into @table values (4,5,’U’)
insert into @table values (5,1,’V’)
insert into @table values (5,2,’W’)
insert into @table values (5,3,’X’)
insert into @table values (5,4,’Y’)
insert into @table values (5,5,’Z’)

set @bit=0

if (@bit=0)
begin
–set @string=’apples’ –CNDEVX
set @x=”
set @y=”
set @cat=”

set @count=LEN(@string)
set @i=1

while (@i<=@count)
begin

select @x=@x+x, @y=@y+y
from @table
where Chr = SUBSTRING(@string,@i,1)

set @i=@i+1
end

set @catnum=@y+@x
set @i=1

set @count=LEN(@catnum)

while (@i<=@count)
begin

select @y=SUBSTRING(@catnum,@i,1),
@x=SUBSTRING(@catnum,@i+1,1)

select @cat=@cat+Chr
from @table
where x=@x and y=@y

–select @y, @x

set @i=@i+2
end

end
else
begin

–set @string='CNDEVX'
set @x=''
set @y=''
set @cat=''
set @catnum=''

set @count=LEN(@string)
set @i=1

while (@i<=@count)
begin

select @catnum=@catnum+y+x
from @table
where Chr=SUBSTRING(@string,@i,1)

set @i=@i+1
end

set @y=LEFT(@catnum,LEN(@catnum)/2)
set @x=right(@catnum,LEN(@catnum)/2)

set @count=LEN(@y)
set @i=1

while (@i<=@count)
begin

select @cat=@cat+Chr
from @table
where x=SUBSTRING(@x,@i,1)
and y=SUBSTRING(@y,@i,1)

set @i=@i+1
end

end

return @cat

— Return the result of the function

END

GO

5. meecrob said

Hey, I’m pretty new to python and first time on praxis, but here is the python solution:

http://pastebin.com/f7f1072a5

P.S I have no idea what is supposed to be done with J.

6. Arnar said

Here’s another Python solution. I wrote it without looking at meecrob’s one, it is interesting to see that they are still quite similar.

def blocks(data, blocksize):
“””Generator that yields elements from xs in blocks.”””
assert(len(data) % blocksize == 0)
for i in xrange(0, len(data), blocksize):
yield data[i:i+blocksize]

key1 = list(blocks(“ABCDEFGHIKLMNOPQRSTUVWXYZ”, 5))
key2 = list(blocks(“37FBO7T20KZUMXYHLS196QW4AVIDGNJPCRE5”, 6))

def code2char(a, b, key):
return key[a][b]

def char2code(c, key):
c = c.upper()
r = [c in row for row in key]
assert any(r)
a = r.index(True)
b = key[a].index(c)
return a, b

def encrypt(s, key):
codes = map(lambda x: char2code(x,key), s)
a, b = zip(*codes)
d = blocks(a+b, 2)
c = “”.join(map(lambda (a,b): code2char(a, b, key), d))
return c

def decrypt(c, key):
d = sum(map(lambda x: char2code(x,key), c), ())
h = len(d)/2
a, b = d[:h], d[h:]
codes = zip(a, b)
s = “”.join(map(lambda (a,b): code2char(a,b,key), codes))
return s

7. Arnar said

Hm, sorry about code formatting (can it be fixed?).

Here’s the code: http://pastie.org/658185

8. Leftware said

This is my dirty C# implementation:

public static string Bifid(string entrada) {
var filas = “1111122222333334444455555”;
var cols = “1234512345123451234512345”;
var alfa = “abcdefghiklmnopqrstuvwxyz”;

for (int i = 0; i < entrada.Length; i++) {
arr1[i] = filas[ind];
arr2[i] = cols[ind];
}
var arr3 = new char[entrada.Length * 2];
Array.ConstrainedCopy(arr1, 0, arr3, 0, arr1.Length);
Array.ConstrainedCopy(arr2, 0, arr3, arr1.Length, arr2.Length);
var sb = new StringBuilder();
for (int i = 0; i < arr3.Length; i += 2) {
var sf = filas.IndexOf(arr3[i]);
var sc = cols.IndexOf(arr3[i + 1], sf);
sb.Append(alfa[sc]);
}

return sb.ToString();
}

9. Paulc said

Here is another version in Python (a bit more object oriented)

10. Christopher said

A ruby solution

class String
def bifid_encipher
self.gsub!(/[^A-Za-z]/,”)
stringify coordinates.transpose.flatten.each_slice(2)
end

def bifid_decipher
stringify coordinates.flatten.each_slice(self.size).to_a.transpose
end

protected
def coordinates
self.upcase.split(//).inject([]) do |a, char|
polybius_square.each_with_index do |array, i|
a << [i, \$_] if \$_ = array =~ /#{char}/
end

a
end
end

def stringify(message)
message.map { |k,v| "%c" % polybius_square[k][v] }.to_s
end

def polybius_square
@square ||= (('A'..'Z').to_a – %w(J)).each_slice(5).map { |a| a.join }
end
end

11. Pete Jones said

Javascript using a 6×6 square.

http://pastebin.com/f44f6043c

12. Kevin Qiu said

In Clojure:

```(ns bifid
(:gen-class))

(defn polybius-square
"Polybius square by the given charset and size"
[charset square-size]
(map #(vector %1 [%2 %3]) charset
(for [x (range 1 (+ 1 square-size)), y (range 1 (+ 1 square-size))] x)
(take (count charset) (cycle (range 1 (+ 1 square-size))))))

(defn- letter-2-code
"Produce a mapping between letters and their codes"
[square]
(letfn [(helper [the-square the-map]
(if (empty? the-square)
the-map
(let [the-item (first the-square)
the-key (first the-item)
the-number (second the-item)]
(recur (rest the-square) (assoc the-map the-key the-number)))))]
(helper square (empty hash-map))))

(defn- transposed-2-letter
"Produce a mapping between the transposed codes to letter"
[square]
(letfn [(helper [the-square the-map]
(if (empty? the-square)
the-map
(let [the-item (first the-square)
the-key (second the-item)
the-letter (first the-item)]
(recur (rest the-square) (assoc the-map the-key the-letter)))))]
(helper square (empty hash-map))))

(defn encode
"Return the message encoded by the specified polybius-square"
[message polybius-square]
(let [l2c (letter-2-code polybius-square)
tr2l (transposed-2-letter polybius-square)]
(apply str
(map #(get tr2l % %) (partition 2 (apply interleave (map #(get l2c % %) message)))))))

(defn decode
"Return the decoded message using the specified polybius-square"
[encoded polybius-square]
(let [l2c (letter-2-code polybius-square)
c2l (transposed-2-letter polybius-square)
codes (apply concat (map #(get l2c % %) encoded))
len (count codes)
parts (partition (/ len 2) codes)]
(apply str (map #(get c2l %1 %1) (map #(vector %1 %2) (first parts) (second parts))))))

(defn -main
"A simple test case entry point"
[]
(let [square (polybius-square "ABCDEFGHIKLMNOPQRSTUVWXYZ" 5)]
(do
(println (encode "PROGRAMMINGPRAXIS" square))
(println (decode "OMQNHHQWUIGBIMWCS" square)))))
```
13. […] best way to learn a language is to use it to solve some non-trivial practical problems. I stumbled this problem on Programming Praxis. It’s about building a Bifid cipher, which I thought could be a […]

14. DotNetter said

Another C# soln.

public class Bifid
{
string[,] KeyMatrix = new string[5,5];

public Bifid()
{
BuildKeyMatrix();
}

private void BuildKeyMatrix()
{
int k = 65;
for(int i = 0; i <5; i++)
{
for(int j = 0; j<5; j++)
{
if(k==74) {k++;} // Dont take j (j ascii = 64)
KeyMatrix[i,j] = ((char)k).ToString();
k++;
}
}
}

public string EncryptDecrypt(string Text, bool Encrypt)
{
int k = 0;
string CharofMessage = string.Empty;
StringBuilder sb1 = new StringBuilder();
StringBuilder sb2 = new StringBuilder();
StringBuilder sbOut = new StringBuilder();
bool HasGotChar = false;

while(k < Text.Length)
{
CharofMessage = Text.Substring(k,1);
for(int i = 0; i <5; i++)
{
for(int j = 0; j<5; j++)
{
if(string.Compare(KeyMatrix[i,j],CharofMessage, true) == 0)
{
sb1.Append(i.ToString());
if(Encrypt)
sb2.Append(j.ToString()); //Use separate string builder for encrypt – ease of coding :-)
else
sb1.Append(j.ToString());
HasGotChar = true;
break;
}
}
if(HasGotChar) // exit the loop if we hit the character
{
HasGotChar = false;
break;
}
}
k++;
}

k = 0;

if(Encrypt)
{
sb1.Append(sb2.ToString()); // combine both
while(k < sb1.Length)
{
sbOut.Append( KeyMatrix[Convert.ToInt32(sb1[k].ToString()),Convert.ToInt32(sb1[k+1].ToString())]);
k += 2;
}
}
else
{
int SplitNum = (sb1.Length) / 2;
while(k < SplitNum)
{
sbOut.Append( KeyMatrix[Convert.ToInt32(sb1[k].ToString()),Convert.ToInt32(sb1[k + SplitNum].ToString())]);
k ++;
}
}

return sbOut.ToString();
}
}

15. fb said

My J solution:

```pre=:(]->&9)@-&65@(a.&i.@toupper)
enc=:|:@((%&2@#,2:)\$[)@(<.@%&5,5&|)
dec=:((2:,%&2@#)\$[)@(<.@%&5,@,.5&|)
pst=:{&a.@(]-<&75)@(5&*@[/+66&+@]/)

encode=:pst@enc@pre
decode=:pst@dec@pre
```
16. Rudi Angela said

Here’s an implementation in Erlang. Source file:
-module(bifid).
-export([encode/1, decode/1]).

encode(Source) ->
frompoints(makecolumns(flattenrows(topoints(Source)))).

decode(Source) ->
frompoints(unflattenrows(flattencolumns(topoints(Source)))).

% flattenrows(PointsList)
% flattens a list of two-integer tuples [{X1, Y1}, {X2, Y2} … ]
% into a list of ints [X1, X2, … Y1, Y2, …]
flattenrows(Points) ->
[X || {X,_} <- Points] ++ [Y || {_,Y}
makepoints(lists:split(length(List) div 2, List), []).

% makepoints({IntsList1, IntsList2}, AccumulatorList)
% Helper function for makepoints, that does most of the work
% Joins corresponding items of the two input lists to two-integer
% tuples and ads the result to accumulator list
% at the end the accumulator list is reversed to get the right order
makepoints({[], _}, Acc) -> lists:reverse(Acc);
makepoints({[X | Xlist], [Y | Ylist]}, Acc) ->
makepoints({Xlist, Ylist}, [{X, Y} | Acc]).

% flattencolumns(PointsList)
% flattens a list of two-integer tuples [{X1, Y1}, {X2, Y2} … ]
% into a list of ints [X1, Y1, X2, Y2, …]
flattencolumns(List) -> flattencolumns(List, []).
flattencolumns([], Acc) -> lists:reverse(Acc);
flattencolumns([{X, Y} | Tail], Acc) ->
flattencolumns(Tail, [Y | [X | Acc]]). % will be reversed

% makecolumns(IntegersList)
% does the inverse operation of flattencolumns
makecolumns(List) -> makecolumns(List, []).

makecolumns([], Acc) -> lists:reverse(Acc);
makecolumns([X | [Y | Tail]], Acc) ->
makecolumns(Tail, [{X, Y} | Acc]).

% topoints(String, Encoding)
% calculates the two-integer tuple that represents a character
% in the given encoding
topoints(Source, {Key, Period}) ->
[divrem( indexof(Char, Key), Period) || Char
frompoints(Source, Key, Period, []).
frompoints([], _Key, _Period, Accumulator) -> lists:reverse(Accumulator);
frompoints([{X, Y} | Tail], Key, Period, Accumulator) ->
Index = (X-1) * Period + (Y),
Char = lists:nth(Index, Key),
frompoints(Tail, Key, Period, [Char | Accumulator]);
frompoints(Any, _, _, Acc) ->
io:format(“Error: ~p, ~p~n”, [Any, Acc]),
Acc.

% divrem(X, Y)
% function to X div Y and X rem Y and return both as a tuple {Div, Rem}
% both values are offset by 1 for convenience
divrem(X, Y) -> divrem(X, Y, 0).
divrem(X, Y, Acc) when X {Acc+1, X+1};
divrem(X, Y, Acc) -> divrem(X – Y, Y, Acc + 1).

% indexof(List, Item)
% As Erlang has no array data type we have to use linked lists.
% The lists module does not have a function to calculate the index
% of an item so here is my implementation.
indexof(Item, List) -> indexof(Item, List, 0).
indexof(_Item, [], Start) -> Start;
indexof(Item, [Head | Tail], Start) ->
if Item =:= Head -> Start;
true -> indexof(Item, Tail, Start + 1)
end.

% encoding()
% convenience method for testing
encoding() -> {“ABCDEFGHIKLMNOPQRSTUVWXYZ”, 5}.

% topoints(List)
% convenience method for testing
topoints(Source) -> topoints(Source, encoding()).

% frompoints(Source)
% convenience method for testing
frompoints(Source) -> frompoints(Source, encoding()).

In the erlang shell you can then enter:
1> c(bifid).
{ok,bifid}
2> bifid:encode(“PROGRAMMINGPRAXIS”).
“OMQNHHQWUIGBIMWCS”
3> E = bifid:encode(“PROGRAMMINGPRAXIS”).
“OMQNHHQWUIGBIMWCS”
4> bifid:decode(E).
“PROGRAMMINGPRAXIS”

17. Andrey said

Help me with Visual Basic code for this program….please!!! (

18. Rohit Phutane said

package com.rohit.classes;

import java.util.*;
import java.util.Map.Entry;

/**
* Here is the java solution..:)
* @author rohitp
*
*/
public class BifidCipher {

public static void main(String[] args) {
Map cipherMap = new HashMap();
int count = 0;
for (int i = 1; i < 6; i++) {
for (int j = 1; j < 6; j++) {
char c = (char) (97 + (count++));
String ij = i + "" + j;
if (c == 'j') {
c = (char) (97 + (count++));
}
cipherMap.put(c, ij);
}
}

String input = "PROGRAMMINGPRAXIS".toLowerCase();
StringBuffer strBuff = new StringBuffer();
for (int i = 0; i < input.length(); i++) {
char c = input.charAt(i);
strBuff.append(cipherMap.get(c));
}
System.out.println("str:- " + strBuff.toString());
String str = strBuff.toString();

StringBuffer newBuff = new StringBuffer();
for (int i = 0; i < str.length(); i++) {
if (i % 2 == 0) {
newBuff.append(str.charAt(i));
}
if (i == str.length() – 1) {
str = str.substring(1, str.length());
for (int j = 0; j < str.length(); j++) {
if (j % 2 == 0) {
newBuff.append(str.charAt(j));
}
}
break;
}
}
String deciText = newBuff.toString();
String temp = "";
for (int i = 0; i 0 && i % 2 != 0 && i < deciText.length() – 1) {
temp += "^";
}
}
String[] deciArr = temp.split("\\^");
String finalVal = "";
for (int i = 0; i < deciArr.length; i++) {
for (Entry entry : cipherMap.entrySet()) {
if (entry.getValue().equals(deciArr[i])) {
finalVal += entry.getKey();
}
}

}
System.out.println(“finalVal:- ” + finalVal);
}

}

19. aruna said

given the mathematical type not the programming type

20. Daniel said

My solution in R. I slightly expanded the key to an eight by eight square in order to include capitals, full stops and spaces.

encode <- function(message) {

poly <- matrix(c(letters,LETTERS,"0","1","2","3","4","5","6","7","8","9"," ","."),nrow=8,byrow=T) ### Create key
split.message <- strsplit(message,"")[] ### Split message into individual characters

tr <- vector(length=nchar(message))
br <- vector(length=nchar(message))

### Create empty vectors (top row and bottom row)

for (i in 1:length(split.message)) {
tr[i] <- which(poly == split.message[i],arr.ind=T)
br[i] <- which(poly == split.message[i],arr.ind=T)
}

### This loop looks up the row () and column () for each character in the message

coded.message <- vector(length=nchar(message))

enc <- c(tr,br) ### Creates a single vector with row and then column numbers for the second step of encoding

for (i in 1:nchar(message)) {
coded.message[i] <- poly[enc[2*i-1],enc[2*i]]
}

### This loop reads the numbers in enc in twos, and returns the corresponding letters in the key

return(paste(coded.message, collapse = ""))

### Joins all the characters up into a single string, and returns the coded message!

}

decode <- function(coded.message) {

poly <- matrix(c(letters,LETTERS,"0","1","2","3","4","5","6","7","8","9"," ","."),nrow=8,byrow=T) #Creates key
splitcoded.message <- strsplit(coded.message,"")[]

dec <- vector(length=nchar(coded.message))

for (i in 1:nchar(coded.message)) {
dec[2*i-1] <- which(poly == splitcoded.message[i],arr.ind=T)
dec[2*i] <- which(poly == splitcoded.message[i],arr.ind=T)
}

decoded.message <- vector(length=nchar(coded.message))

for (i in 1:nchar(coded.message)) {
decoded.message[i] encode(“Merry Christmas”)
 “GsFyrsiwHi05cCc”
> decode(“GsFyrsiwHi05cCc”)
 “Merry Christmas”

21. Daniel said

Sloppy copy and pasting technique messed up the end of that. Below is correct code:

encode <- function(message) {

poly <- matrix(c(letters,LETTERS,"0","1","2","3","4","5","6","7","8","9"," ","."),nrow=8,byrow=T) #Creates key
split.message <- strsplit(message,"")[]

tr <- vector(length=nchar(message))
br <- vector(length=nchar(message))

for (i in 1:length(split.message)) {
tr[i] <- which(poly == split.message[i],arr.ind=T)
br[i] <- which(poly == split.message[i],arr.ind=T)
}

coded.message <- vector(length=nchar(message))

enc <- c(tr,br)

for (i in 1:nchar(message)) {
coded.message[i] <- poly[enc[2*i-1],enc[2*i]]
}

return(paste(coded.message, collapse = ""))
}

decode <- function(coded.message) {

poly <- matrix(c(letters,LETTERS,"0","1","2","3","4","5","6","7","8","9"," ","."),nrow=8,byrow=T) #Creates key
splitcoded.message <- strsplit(coded.message,"")[]

dec <- vector(length=nchar(coded.message))

for (i in 1:nchar(coded.message)) {
dec[2*i-1] <- which(poly == splitcoded.message[i],arr.ind=T)
dec[2*i] <- which(poly == splitcoded.message[i],arr.ind=T)
}

decoded.message <- vector(length=nchar(coded.message))

for (i in 1:nchar(coded.message)) {
decoded.message[i] encode(“Merry Christmas”)
 “GsFyrsiwHi05cCc”
> decode(“GsFyrsiwHi05cCc”)
 “Merry Christmas”

22. Daniel said

Something strange is going on here. Administrators feel free to delete previous comments. One more time….

encode <- function(message) {

poly <- matrix(c(letters,LETTERS,"0","1","2","3","4","5","6","7","8","9"," ","."),nrow=8,byrow=T) #Creates key
split.message <- strsplit(message,"")[]

tr <- vector(length=nchar(message))
br <- vector(length=nchar(message))

for (i in 1:length(split.message)) {
tr[i] <- which(poly == split.message[i],arr.ind=T)
br[i] <- which(poly == split.message[i],arr.ind=T)
}

coded.message <- vector(length=nchar(message))

enc <- c(tr,br)

for (i in 1:nchar(message)) {
coded.message[i] <- poly[enc[2*i-1],enc[2*i]]
}

return(paste(coded.message, collapse = ""))
}

decode <- function(coded.message) {

poly <- matrix(c(letters,LETTERS,"0","1","2","3","4","5","6","7","8","9"," ","."),nrow=8,byrow=T) #Creates key
splitcoded.message <- strsplit(coded.message,"")[]

dec <- vector(length=nchar(coded.message))

for (i in 1:nchar(coded.message)) {
dec[2*i-1] <- which(poly == splitcoded.message[i],arr.ind=T)
dec[2*i] <- which(poly == splitcoded.message[i],arr.ind=T)
}

decoded.message <- vector(length=nchar(coded.message))

for (i in 1:nchar(coded.message)) {
decoded.message[i] <- poly[dec[i],dec[i+nchar(coded.message)]]
}

return(paste(decoded.message, collapse = ""))
}