(phixonline)-->
with javascript_semantics
constant keyword = "Playfair example",
option = 'Q' -- ignore Q
-- option = 'J' -- replace J with I
sequence table,
findchar
procedure build_table()
table = repeat(repeat(' ',5),5)
findchar = repeat(0,26)
findchar[option-'A'+1] = {0,0}
-- (note any (J/Q) in keyword are simply ignored)
string alphabet = upper(keyword) & tagset('Z','A')
integer i=1, j=1
for k=1 to length(alphabet) do
integer c = alphabet[k]
if c>='A' and c<='Z' then
integer d = c-'A'+1
if findchar[d]=0 then
table[i][j] = c
findchar[d] = {i,j}
j += 1
if j=6 then
i += 1
if i=6 then exit end if -- table filled
j = 1
end if
end if
end if
end for
end procedure
build_table()
function clean_text(string plaintext)
--
-- get rid of any non-letters and insert X between duplicate letters
--
plaintext = upper(plaintext)
string cleantext = ""
integer prevChar = -1
for i=1 to length(plaintext) do
integer nextChar = plaintext[i]
if nextChar>='A' and nextChar<='Z'
and (nextChar!='Q' or option!='Q') then
if nextChar='J' and option='J' then nextChar = 'I' end if
if nextChar=prevChar then
cleantext &= 'X'
end if
cleantext &= nextChar
prevChar = nextChar
end if
end for
if odd(length(cleantext)) then
-- dangling letter at end so add another letter to complete digraph
cleantext &= iff(cleantext[$]='X'?'Z':'X')
end if
return cleantext
end function
function remove_x(string text)
for i=2 to length(text)-1 do
if text[i]='X'
and ((text[i-1]=' ' and text[i-2]=text[i+1]) or
(text[i+1]=' ' and text[i-1]=text[i+2])) then
text[i] = '_'
end if
end for
return text
end function
function playfair(string text, integer step, sequence d)
--
-- text may be the plaintext or the encoded version
-- step is 2 for plaintext, 3 for encoded(/skip spaces)
-- d is {2,3,4,5,1} instead of mod(+1,5), or
-- {5,1,2,3,4} -- -1
--
string res = ""
for i=1 to length(text) by step do
integer {row1, col1} = findchar[text[i]-'A'+1],
{row2, col2} = findchar[text[i+1]-'A'+1]
if i>1 then res &= " " end if
if row1=row2 then
{col1,col2} = {d[col1],d[col2]}
elsif col1=col2 then
{row1,row2} = {d[row1],d[row2]}
else
{col1,col2} = {col2,col1}
end if
res &= table[row1][col1] & table[row2][col2]
end for
return res
end function
function encode(string plaintext)
return playfair(clean_text(plaintext),2,{2,3,4,5,1})
end function
function decode(string ciphertext)
-- ciphertext includes spaces we need to skip, hence by 3
return remove_x(playfair(ciphertext,3,{5,1,2,3,4}))
end function
printf(1,"Playfair keyword : %s\n",{keyword})
printf(1,"Option: J=I or no Q (J/Q) : %s\n",option)
printf(1,"The table to be used is :\n\n%s\n\n",{join(table,"\n")})
string plaintext = "Hide the gold...in the TREESTUMP!!!!",
encoded = encode(plaintext),
decoded = decode(encoded)
printf(1,"The plain text : %s\n\n",{plaintext})
printf(1,"Encoded text is : %s\n",{encoded})
printf(1,"Decoded text is : %s\n",{decoded})