Playfair cipher: Difference between revisions

m
m (→‎{{header|Python}}: Fix link: Perl 6 --> Raku)
m (→‎{{header|Wren}}: Minor tidy)
 
(24 intermediate revisions by 14 users not shown)
Line 1:
{{draft task}} [[Category:Encryption]]
 
{{task}}
 
;Task:
Implement a [[wp: Playfair cipher| Playfair cipher]] for encryption and decryption.
 
 
The user must be able to choose J = I or no Q in the alphabet.
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.
;Output example:
HI DE TH EG OL DI NT HE TR EX ES TU MP
<br><br>
 
=={{header|11l}}==
{{trans|Python}}
 
<syntaxhighlight lang="11l">F uniq(seq)
[Char] seen
L(x) seq
I x !C seen
seen.append(x)
R seen
 
F partition(seq, n)
R (0 .< seq.len).step(n).map(i -> @seq[i .< i + @n])
 
F canonicalize(s)
R s.uppercase().filter(c -> c.is_uppercase()).join(‘’).replace(‘J’, ‘I’)
 
T Playfair
[String = String] dec, enc
 
F (key)
V m = partition(uniq(canonicalize(key‘ABCDEFGHIJKLMNOPQRSTUVWXYZ’)), 5)
 
L(row) m
L(i, j) cart_product(0.<5, 0.<5)
I i != j
.enc[row[i]‘’row[j]] = row[(i + 1) % 5]‘’row[(j + 1) % 5]
 
L(ci) 5
V c = [m[0][ci], m[1][ci], m[2][ci], m[3][ci], m[4][ci]]
L(i, j) cart_product(0.<5, 0.<5)
I i != j
.enc[c[i]‘’c[j]] = c[(i + 1) % 5]‘’c[(j + 1) % 5]
 
L(i1, j1, i2, j2) cart_product(0.<5, 0.<5, 0.<5, 0.<5)
I i1 != i2 & j1 != j2
.enc[m[i1][j1]‘’m[i2][j2]] = m[i1][j2]‘’m[i2][j1]
 
.dec = Dict(.enc.map((k, v) -> (v, k)))
 
F encode(txt)
V c = canonicalize(txt)
[String] lst
V i = 0
L i < c.len - 1
I c[i + 1] == c[i]
lst [+]= c[i]‘X’
i++
E
lst [+]= c[i]‘’c[i + 1]
i += 2
I i == c.len - 1
lst [+]= c.last‘X’
R lst.map(a -> @.enc[a]).join(‘ ’)
 
F decode(encoded)
R partition(canonicalize(encoded), 2).map(p -> @.dec[p]).join(‘ ’)
 
V playfair = Playfair(‘Playfair example’)
V orig = ‘Hide the gold in...the TREESTUMP!!!’
print(‘Original: ’orig)
V enc = playfair.encode(orig)
print(‘Encoded: ’enc)
print(‘Decoded: ’playfair.decode(enc))</syntaxhighlight>
 
{{out}}
<pre>
Original: Hide the gold in...the TREESTUMP!!!
Encoded: BM OD ZB XD NA BE KU DM UI XM MO UV IF
Decoded: HI DE TH EG OL DI NT HE TR EX ES TU MP
</pre>
 
=={{header|APL}}==
{{works with|Dyalog APL}}
<syntaxhighlight lang="apl">⍝⍝⍝⍝ Utility functions
 
⍝ convert to uppercase
UpCase ← { 1 ⎕C ⍵ }
 
⍝ remove non-letters
JustLetters ← { ⍵ /⍨ ⍵∊⎕A }
 
⍝ replace 'J's with 'I's
ReplaceJ ← { ('J' ⎕R 'I') ⍵ }
 
⍝ Insert an 'X' between repeated letters
SplitDouble ← { (' '⎕R'X') ⍵ \⍨ 1,~⍵=1⌽⍵ }
 
⍝ Append an 'X' if the message is not of even length
PadEven ← { ⍵,(2|≢⍵) ⍴ 'X' }
 
⍝ Split text up into letter pairs
Pairs ← { (1=2|⍳≢⍵) ⊂ ∊ ⍵ }
 
⍝ Group text into chunks of five letters
Groups ← { (1=5|⍳≢⍵) ⊂ ∊ ⍵ }
 
⍝ Shift within 1-5 based on left arg (0 for +1,1 for -1)
Shift ← { ⍺ ← 0 ⋄ 1+5|(⍺+1)⌷⍵,3+⍵ }
 
⍝⍝⍝⍝ Playfair implementation
 
⍝ All the things we have to do to the plaintext, chained together
PreparePlaintext ← { PadEven SplitDouble ReplaceJ JustLetters UpCase ∊ ⍵ }
 
⍝ Ditto for ciphertext
PrepareCiphertext ← { JustLetters UpCase ∊ ⍵ }
 
⍝ Create the grid from the key
PrepareKey ← { 5 5⍴ ∪ ReplaceJ (JustLetters UpCase ⍵),⎕A }
 
⍝ Encode or decode a single pair of letters
∇resultPair ← grid TransformPair args;mode;inPair;l;r;i1;j1;i2;j2
mode inPair ← args
l r ← inPair
i1 j1 ← ⊃⍸grid=l
i2 j2 ← ⊃⍸grid=r
:If i1=i2
j1 ← mode Shift j1
j2 ← mode Shift j2
:Else
:If j1=j2
i1 ← mode Shift i1
i2 ← mode Shift i2
:Else
j1 j2 ← j2 j1
:EndIf
:EndIf
resultPair ← grid[(i1 j1)(i2 j2)]
 
⍝ Encode or decode an entire message
∇resultText ← grid TransformText args; mode; inText
mode inText ← args
resultText ← Groups ∊ { grid TransformPair mode ⍵ } ¨ Pairs inText
 
⍝ Specific transforms for each direction including key and text preparation
∇cipher ← key EncodeText plain
cipher ← (PrepareKey key) TransformText 0 (PreparePlaintext plain)
 
∇plain ← key DecodeText cipher
plain ← (PrepareKey key) TransformText 1 (PrepareCiphertext cipher)
 
⍝ Demo
key ← 'Playfair example'
plain ← 'Hide the gold in the tree stump.'
⎕ ← cipher ← key EncodeText plain
⎕ ← key DecodeText cipher</syntaxhighlight>
 
{{Out}}<pre> ⎕ ← cipher ← key EncodeText plain
┌─────┬─────┬─────┬─────┬─────┬─┐
│BMODZ│BXDNA│BEKUD│MUIXM│MOUVI│F│
└─────┴─────┴─────┴─────┴─────┴─┘
</pre>
<pre> ⎕ ← key DecodeText cipher
┌─────┬─────┬─────┬─────┬─────┬─┐
│HIDET│HEGOL│DINTH│ETREX│ESTUM│P│
└─────┴─────┴─────┴─────┴─────┴─┘
</pre>
 
=={{header|C++}}==
<langsyntaxhighlight lang="cpp">#include <iostream>
#include <string>
 
Line 118 ⟶ 288:
cout << "Enter the text: "; getline( cin, txt );
playfair pf; pf.doIt( key, txt, ij, e ); return system( "pause" );
}</langsyntaxhighlight>
{{out}}<pre>
(E)ncode or (D)ecode? e
Line 142 ⟶ 312:
=={{header|D}}==
{{trans|Python}}
<langsyntaxhighlight lang="d">import std.stdio, std.array, std.algorithm, std.range, std.ascii,
std.conv, std.string, std.regex, std.typecons;
 
Line 212 ⟶ 382:
writeln(" Encoded: ", enc);
writeln(" Decoded: ", pf.decode(enc));
}</langsyntaxhighlight>
{{out}}
<pre>Original: Hide the gold in...the TREESTUMP!!!
Line 219 ⟶ 389:
 
=={{header|FreeBASIC}}==
<langsyntaxhighlight lang="freebasic">' FB 1.05.0 Win64
 
Enum PlayFairOption
Line 374 ⟶ 544:
Print
Print "Press any key to quit"
Sleep</langsyntaxhighlight>
Sample input/output:
{{out}}
Line 396 ⟶ 566:
=={{header|Go}}==
{{trans|Kotlin}}
<langsyntaxhighlight lang="go">package main
 
import (
Line 603 ⟶ 773:
decodedText := pf.decode(encodedText)
fmt.Println("Deccoded text is :", decodedText)
}</langsyntaxhighlight>
 
{{out}}
Line 627 ⟶ 797:
{{incorrect|Haskell|TREESTUMP -> TREXSTUMPX, should be TREXESTUMP}}
(My guess is that map (\[x, y] -> if x == y then [x, 'x'] else [x, y]).chunksOf 2 is simply discarding the y. [[User:Petelomax|Pete Lomax]] ([[User talk:Petelomax|talk]]) 05:54, 13 October 2018 (UTC))
<langsyntaxhighlight lang="haskell">
import Control.Monad (guard)
import Data.Array (Array, assocs, elems, listArray, (!))
Line 729 ⟶ 899:
| odd (length str) = str ++ "x"
| otherwise = str
</syntaxhighlight>
</lang>
 
<pre>
Line 740 ⟶ 910:
 
=={{header|J}}==
{{incorrect|J|TREESTUMP -> TREXSTUMPX, should be TREXESTUMP}}
Rather than implement two versions of the rules, one for encrypt, one for decrypt, let's just make a lookup table (mapping character pairs to character pairs). To decrypt we can look up in the other direction.
 
'''Implementation:'''
<syntaxhighlight lang="j">choose=: verb define
 
sel=. 'Q' e. y
<lang J>choose=:3 :0
alph=: (sel { 'JQ') -.~ a. {~ 65 + i.26
sel=. 'Q'e.y
norm=: [: dedouble alph restrict ('I' I.@:=&'J'@]} ])`(-.&'Q')@.sel@toupper
alph=:(sel{'JQ')-.~a.{~65+i.26
norm=: alph restrict('I' I.@:=&'J'@]} ])`(-.&'Q')@.sel@toupper
''
)
 
restrict=: ] -. -.~
choose 'Q'
 
splitDigraph=: ,`([,'X',])@.((= {.) *. 2 | #@])
setkey=:3 :0
dedouble=: splitDigraph/&.|. NB. progressively split digraphs in string
 
choose 'Q'
setkey=: verb define
key=. ~.norm y,alph
ref=: ,/ 2{."1 ~."1 (,"0/~ alph) ,"1 norm 'XQV'
mode=. #. =/"2 inds=. 5 5#:key i. ref
inds0=. (0 3,:2 1)&{@,"2 inds
inds1=. 5|1 0 +"1 inds NB. same column
inds2=. 5|0 1 +"1 inds NB. same row
alt=: key {~ 5 #. mode {"_1 inds0 ,"2 3 inds1 ,:"2 inds2
i. 0 0
)
 
pairs=: 3verb define :0
2{."1 -.&' '"1 ~."1 (_2]\ norm y) ,"1 'XQV'
)
 
encrypt=:3 :0verb define
,;:inv ;/ alt{~ref i. pairs y
)
decrypt=: verb define
, ref{~alt i. pairs y
)</syntaxhighlight>
 
'''Example use:'''
decrypt=:3 :0
<syntaxhighlight lang="j"> choose 'IJ'
,ref{~alt i. pairs y
)</lang>
 
Example use:
 
<lang J> choose 'IJ'
 
setkey 'playfair example'
encrypt 'Hide the gold in the tree stump'
BM OD ZB XD NA BE KU DM UI XM MO UV IF
BMODZBXDNABEKUDMUIXMKZZRYI
decrypt 'BMODZBXDNABEKUDMUIXMKZZRYIBM OD ZB XD NA BE KU DM UI XM MO UV IF'
HIDETHEGOLDINTHETREXESTUMP</syntaxhighlight>
HIDETHEGOLDINTHETREXSTUMPX</lang>
 
=={{header|Java}}==
<langsyntaxhighlight lang="java">import java.awt.Point;
import java.util.Scanner;
 
Line 891 ⟶ 1,063:
return text.toString();
}
}</langsyntaxhighlight>
 
=== alternative version ===
 
<langsyntaxhighlight lang="java">import java.util.Scanner;
public class PlayfairCipherEncryption
Line 1,099 ⟶ 1,271:
sc.close();
}
}</langsyntaxhighlight>
 
=={{header|Julia}}==
<langsyntaxhighlight lang="julia">function playfair(key, txt, isencode=true, from = "J", to = "")
to = (to == "" && from == "J") ? "I" : to
 
Line 1,162 ⟶ 1,334:
 
println("Decoded: ", playfair("Playfair example", encoded, false))
</langsyntaxhighlight>{{out}}
<pre>
Original: Hide the gold in...the TREESTUMP!!!
Line 1,171 ⟶ 1,343:
=={{header|Kotlin}}==
{{trans|FreeBASIC}}
<langsyntaxhighlight lang="scala">// version 1.0.5-2
 
enum class PlayfairOption {
Line 1,303 ⟶ 1,475:
val decodedText = playfair.decode(encodedText)
println("Decoded text is : $decodedText")
}</langsyntaxhighlight>
 
{{out}}
Line 1,322 ⟶ 1,494:
Decoded text is : HI DE TH EG OL DI NT HE TR EX ES TU MP
</pre>
 
=={{header|Mathematica}}/{{header|Wolfram Language}}==
<syntaxhighlight lang="mathematica">ClearAll[MakeTranslationTable, PlayfairCipher, PlayfairDecipher]
MakeTranslationTable[tt_List] := Module[{poss, in, out},
poss = Tuples[Tuples[Range[5], 2], 2];
Table[
If[p[[1, 1]] == p[[2, 1]],
(* same row *)
{in, out} = {p, {{p[[1, 1]], Mod[p[[1, 2]] + 1, 5, 1]}, {p[[2, 1]], Mod[p[[2, 2]] + 1, 5, 1]}}};
,
If[p[[1, 2]] == p[[2, 2]],
(* same column *)
{in, out} = {p, {{Mod[p[[1, 1]] + 1, 5, 1], p[[1, 2]]}, {Mod[p[[2, 1]] + 1, 5, 1], p[[2, 2]]}}};
,
(*rectangle*)
{in, out} = {p, {{p[[1, 1]], p[[2, 2]]}, {p[[2, 1]], p[[1, 2]]}}};
]
];
StringJoin[Extract[tt, in]] -> StringJoin[Extract[tt, out]]
,
{p, poss}
]
]
PlayfairCipher[txt_String, key_String, iisj_ : True] :=
Module[{text, tt},
text = RemoveDiacritics[ToUpperCase[txt]];
tt = RemoveDiacritics[ToUpperCase[key]] <> CharacterRange["A", "Z"];
text //= StringReplace[Except[Alternatives @@ CharacterRange["A", "Z"]] -> ""];
tt //= StringReplace[Except[Alternatives @@ CharacterRange["A", "Z"]] -> ""];
If[iisj,
tt //= StringReplace["J" -> "I"];
text //= StringReplace["J" -> "I"];
,
tt //= StringReplace["Q" -> ""];
text //= StringReplace["Q" -> ""];
];
tt //= Characters /* DeleteDuplicates;
text = FixedPoint[StringReplace[#, x_ ~~ x_ :> x ~~ "X" ~~ x, 1] &, text];
If[OddQ[StringLength[text]], text = text <> "X"];
If[Length[tt] == 25,
tt = Partition[tt, 5];
tt = MakeTranslationTable[tt];
text = StringPartition[text, 2];
StringRiffle[text /. tt, " "]
,
Print["Something went wrong!"]
]
]
PlayfairDecipher[txt_String, key_String, iisj_ : True] :=
Module[{text, tt},
text = RemoveDiacritics[ToUpperCase[txt]];
tt = RemoveDiacritics[ToUpperCase[key]] <> CharacterRange["A", "Z"];
text //= StringReplace[Except[Alternatives @@ CharacterRange["A", "Z"]] -> ""];
tt //= StringReplace[Except[Alternatives @@ CharacterRange["A", "Z"]] -> ""];
If[iisj,
tt //= StringReplace["J" -> "I"];
text //= StringReplace["J" -> "I"];
,
tt //= StringReplace["Q" -> ""];
text //= StringReplace["Q" -> ""];
];
tt //= Characters /* DeleteDuplicates;
If[OddQ[StringLength[text]], text = text <> "X"];
If[Length[tt] == 25,
tt = Partition[tt, 5];
tt = MakeTranslationTable[tt];
text = StringPartition[text, 2];
StringRiffle[text /. (Reverse /@ tt), " "]
,
Print["Something went wrong!"]
]
]
PlayfairCipher["Hide the gold in...the TREESTUMP!!!", "Playfair example"]
PlayfairDecipher[%, "Playfair example"]</syntaxhighlight>
{{out}}
<pre>BM OD ZB XD NA BE KU DM UI XM MO UV IF
HI DE TH EG OL DI NT HE TR EX ES TU MP</pre>
 
=={{header|Nim}}==
{{trans|Java}}
<syntaxhighlight lang="nim">import pegs, strutils
 
type
Position = tuple[x, y: int]
Playfair = object
positions: array['A'..'Z', Position]
table: array[5, array[5, char]]
 
const None: Position = (-1, -1) # Default value for positions.
 
 
proc initPlayfair(key: string; jti: bool): Playfair =
 
for item in result.positions.mitems: item = None
 
var alphabet = key & "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
alphabet = if jti: alphabet.replace('J', 'I')
else: alphabet.replace("Q", "")
 
var k = 0
for ch in alphabet:
if result.positions[ch] == None:
result.table[k div 5][k mod 5] = ch
result.positions[ch] = (k mod 5, k div 5)
inc k
 
 
proc codec(playfair: Playfair; text: string; direction: int): string =
 
result.setLen(text.len)
 
for i in countup(0, text.high, 2):
var
(col1, row1) = playfair.positions[text[i]]
(col2, row2) = playfair.positions[text[i + 1]]
 
if row1 == row2:
col1 = (col1 + direction) mod 5
col2 = (col2 + direction) mod 5
elif col1 == col2:
row1 = (row1 + direction) mod 5
row2 = (row2 + direction) mod 5
else:
swap col1, col2
 
result[i] = playfair.table[row1][col1]
result[i + 1] = playfair.table[row2][col2]
 
 
proc encode(playfair: Playfair; text: string): string =
var
text = text
i = 0
 
while i < text.len:
if i == text.high:
if (text.len and 1) != 0:
text.add 'X'
elif text[i] == text[i + 1]:
text.insert("X", i + 1)
inc i, 2
 
result = playfair.codec(text, 1)
 
 
proc decode(playfair: Playfair; text: string): string =
result = playfair.codec(text, 4)
 
 
proc prompt(msg: string): string =
stdout.write msg
try:
result = stdin.readLine()
except EOFError:
echo ""
quit getCurrentExceptionMsg(), QuitFailure
 
 
when isMainModule:
 
var key: string
while key.len <= 6:
key = prompt("Enter an encryption key (min letters 6): ").toUpperAscii().replace(peg"[^A-Z]")
 
var text: string
while text.len == 0:
text = prompt("Enter the message: ").toUpperAscii().replace(peg"[^A-Z]")
 
var answer: string
while answer notin ["y", "n"]:
answer = prompt("Replace J with I? y/n: ").toLowerAscii()
let jti = (answer == "y")
 
let playfair = initPlayfair(key, jti)
let enc = playfair.encode(text)
let dec = playfair.decode(enc)
 
echo "Encoded message: ", enc
echo "Decoded message: ", dec</syntaxhighlight>
 
{{out}}
<pre>Enter an encryption key (min letters 6): Playfair example
Enter the message: Hide the gold...in the TREESTUMP!!!
Replace J with I? y/n: y
Encoded message: BMODZBXDNABEKUDMUIXMMOUVIF
Decoded message: HIDETHEGOLDINTHETREXESTUMP</pre>
 
=={{header|NetRexx}}==
<langsyntaxhighlight NetRexxlang="netrexx">/* NetRexx */
options replace format comments java crossref symbols nobinary
 
Line 1,489 ⟶ 1,847:
 
return
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 1,512 ⟶ 1,870:
 
=={{header|ooRexx}}==
<langsyntaxhighlight lang="oorexx">/*---------------------------------------------------------------------
* REXX program implements a PLAYFAIR cipher (encryption & decryption).
* 11.11.2013 Walter Pachl revamped, for ooRexx, the REXX program
Line 1,709 ⟶ 2,067:
d=d||substr(x,j,2)' '
End
Return strip(d)</langsyntaxhighlight>
Output (sample):
<pre>old cipher key: this is my little key
Line 1,732 ⟶ 2,090:
=={{header|Perl}}==
{{trans|Raku}}
<langsyntaxhighlight lang="perl">use Math::Cartesian::Product;
 
# Pregenerate all forward and reverse translations
Line 1,803 ⟶ 2,161:
print " orig:\t$orig\n";
print "black:\t$black\n";
print " red:\t$red\n";</langsyntaxhighlight>
{{out}}
<pre> orig: Hide the gold in...the TREESTUMP!!!
Line 1,812 ⟶ 2,170:
=={{header|Phix}}==
Originally translated from Kotlin, now uses a combined routine (playfair) for encoding and decoding, and direct char lookups, and x removal.
<!--<syntaxhighlight lang="phix">(phixonline)-->
<lang Phix>sequence table,
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
findchar
<span style="color: #008080;">constant</span> <span style="color: #000000;">keyword</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"Playfair example"</span><span style="color: #0000FF;">,</span>
 
<span style="color: #000000;">option</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">'Q'</span> <span style="color: #000080;font-style:italic;">-- ignore Q
type pfoption(integer option)
-- option = 'J' -- replace J with I</span>
return find(option,"QJ")!=0
end type
 
pfoption pfo -- 'Q' or 'J'
<span style="color: #004080;">sequence</span> <span style="color: #000000;">table</span><span style="color: #0000FF;">,</span>
procedure build_table(string keyword, integer option)
<span style="color: #000000;">findchar</span>
-- option should be 'Q' to ignore Q, or 'J' to replace Js with I
pfo = option
<span style="color: #008080;">procedure</span> <span style="color: #000000;">build_table</span><span style="color: #0000FF;">()</span>
table = repeat(repeat(' ',5),5)
<span style="color: #000000;">table</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #008000;">' '</span><span style="color: #0000FF;">,</span><span style="color: #000000;">5</span><span style="color: #0000FF;">),</span><span style="color: #000000;">5</span><span style="color: #0000FF;">)</span>
findchar = repeat(0,26)
<span style="color: #000000;">findchar</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">26</span><span style="color: #0000FF;">)</span>
findchar[pfo-'A'+1] = {0,0}
<span style="color: #000000;">findchar</span><span style="color: #0000FF;">[</span><span style="color: #000000;">option</span><span style="color: #0000FF;">-</span><span style="color: #008000;">'A'</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">}</span>
-- (note that any pfo (J/Q) in keyword are simply ignored)
<span style="color: #000080;font-style:italic;">-- (note any (J/Q) in keyword are simply ignored)</span>
string alphabet = upper(keyword) & "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
<span style="color: #004080;">string</span> <span style="color: #000000;">alphabet</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">upper</span><span style="color: #0000FF;">(</span><span style="color: #000000;">keyword</span><span style="color: #0000FF;">)</span> <span style="color: #0000FF;">&</span> <span style="color: #7060A8;">tagset</span><span style="color: #0000FF;">(</span><span style="color: #008000;">'Z'</span><span style="color: #0000FF;">,</span><span style="color: #008000;">'A'</span><span style="color: #0000FF;">)</span>
integer i=1, j=1
<span style="color: #004080;">integer</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">j</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span>
for k=1 to length(alphabet) do
<span style="color: #008080;">for</span> <span style="color: #000000;">k</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">alphabet</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
integer c = alphabet[k]
<span style="color: #004080;">integer</span> <span style="color: #000000;">c</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">alphabet</span><span style="color: #0000FF;">[</span><span style="color: #000000;">k</span><span style="color: #0000FF;">]</span>
if c>='A' and c<='Z' then
<span style="color: #008080;">if</span> <span style="color: #000000;">c</span><span style="color: #0000FF;">>=</span><span style="color: #008000;">'A'</span> <span style="color: #008080;">and</span> <span style="color: #000000;">c</span><span style="color: #0000FF;"><=</span><span style="color: #008000;">'Z'</span> <span style="color: #008080;">then</span>
integer d = c-'A'+1
<span style="color: #004080;">integer</span> <span style="color: #000000;">d</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">c</span><span style="color: #0000FF;">-</span><span style="color: #008000;">'A'</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span>
if findchar[d]=0 then
<span style="color: #008080;">if</span> <span style="color: #000000;">findchar</span><span style="color: #0000FF;">[</span><span style="color: #000000;">d</span><span style="color: #0000FF;">]=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span>
table[i][j] = c
<span style="color: #000000;">table</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">][</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">c</span>
findchar[d] = {i,j}
<span style="color: #000000;">findchar</span><span style="color: #0000FF;">[</span><span style="color: #000000;">d</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">i</span><span style="color: #0000FF;">,</span><span style="color: #000000;">j</span><span style="color: #0000FF;">}</span>
j += 1
<span style="color: #000000;">j</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
if j=6 then
<span style="color: #008080;">if</span> <span style="color: #000000;">j</span><span style="color: #0000FF;">=</span><span style="color: #000000;">6</span> <span style="color: #008080;">then</span>
i += 1
if i<span style=6"color: then#000000;">i</span> exit<span endstyle="color: if#0000FF;">+=</span> --<span tablestyle="color: filled#000000;">1</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">6</span> <span style="color: #008080;">then</span> <span style="color: #008080;">exit</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span> <span style="color: #000080;font-style:italic;">-- table filled</span>
j = 1
<span style="color: #000000;">j</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span>
end if
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
end if
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
end if
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
end for
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
end procedure
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
 
<span style="color: #000000;">build_table</span><span style="color: #0000FF;">()</span>
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 pfo!='Q') then
if nextChar='J' and pfo='J' then nextChar = 'I' end if
if nextChar=prevChar then
cleantext &= 'X'
end if
cleantext &= nextChar
prevChar = nextChar
end if
end for
if remainder(length(cleantext),2) then
-- dangling letter at end so add another letter to complete digram
cleantext &= iff(cleantext[$]='X'?'Z':'X')
end if
return cleantext
end function
<span style="color: #008080;">function</span> <span style="color: #000000;">clean_text</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">plaintext</span><span style="color: #0000FF;">)</span>
function remove_x(string text)
<span style="color: #000080;font-style:italic;">--
for i=2 to length(text)-1 do
-- get rid of any non-letters and insert X between duplicate letters
if text[i]='X'
--</span>
and ((text[i-1]=' ' and text[i-2]=text[i+1]) or
<span style="color: #000000;">plaintext</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">upper</span><span style="color: #0000FF;">(</span><span style="color: #000000;">plaintext</span><span style="color: #0000FF;">)</span>
(text[i+1]=' ' and text[i-1]=text[i+2])) then
<span style="color: #004080;">string</span> <span style="color: #000000;">cleantext</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">""</span>
text[i] = '_'
<span style="color: #004080;">integer</span> <span style="color: #000000;">prevChar</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">1</span>
end if
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">plaintext</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
end for
<span style="color: #004080;">integer</span> <span style="color: #000000;">nextChar</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">plaintext</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span>
return text
<span style="color: #008080;">if</span> <span style="color: #000000;">nextChar</span><span style="color: #0000FF;">>=</span><span style="color: #008000;">'A'</span> <span style="color: #008080;">and</span> <span style="color: #000000;">nextChar</span><span style="color: #0000FF;"><=</span><span style="color: #008000;">'Z'</span>
end function
<span style="color: #008080;">and</span> <span style="color: #0000FF;">(</span><span style="color: #000000;">nextChar</span><span style="color: #0000FF;">!=</span><span style="color: #008000;">'Q'</span> <span style="color: #008080;">or</span> <span style="color: #000000;">option</span><span style="color: #0000FF;">!=</span><span style="color: #008000;">'Q'</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
 
<span style="color: #008080;">if</span> <span style="color: #000000;">nextChar</span><span style="color: #0000FF;">=</span><span style="color: #008000;">'J'</span> <span style="color: #008080;">and</span> <span style="color: #000000;">option</span><span style="color: #0000FF;">=</span><span style="color: #008000;">'J'</span> <span style="color: #008080;">then</span> <span style="color: #000000;">nextChar</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">'I'</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
function playfair(string text, integer step, sequence d)
<span style="color: #008080;">if</span> <span style="color: #000000;">nextChar</span><span style="color: #0000FF;">=</span><span style="color: #000000;">prevChar</span> <span style="color: #008080;">then</span>
string res = ""
<span style="color: #000000;">cleantext</span> <span style="color: #0000FF;">&=</span> <span style="color: #008000;">'X'</span>
for i=1 to length(text) by step do
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
integer {row1, col1} = findchar[text[i]-'A'+1],
<span style="color: #000000;">cleantext</span> <span style="color: #0000FF;">&=</span> <span style="color: #000000;">nextChar</span>
{row2, col2} = findchar[text[i+1]-'A'+1]
<span style="color: #000000;">prevChar</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">nextChar</span>
if i>1 then res &= " " end if
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
if row1=row2 then
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
res &= table[row1][d[col1]] & table[row2][d[col2]]
<span style="color: #008080;">if</span> <span style="color: #7060A8;">odd</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cleantext</span><span style="color: #0000FF;">))</span> <span style="color: #008080;">then</span>
elsif col1=col2 then
<span style="color: #000080;font-style:italic;">-- dangling letter at end so add another letter to complete digraph</span>
res &= table[d[row1]][col1] & table[d[row2]][col2]
<span style="color: #000000;">cleantext</span> <span style="color: #0000FF;">&=</span> <span style="color: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cleantext</span><span style="color: #0000FF;">[$]=</span><span style="color: #008000;">'X'</span><span style="color: #0000FF;">?</span><span style="color: #008000;">'Z'</span><span style="color: #0000FF;">:</span><span style="color: #008000;">'X'</span><span style="color: #0000FF;">)</span>
else
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
res &= table[row1][col2] & table[row2][col1]
<span style="color: #008080;">return</span> <span style="color: #000000;">cleantext</span>
end if
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
end for
return res
<span style="color: #008080;">function</span> <span style="color: #000000;">remove_x</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">text</span><span style="color: #0000FF;">)</span>
end function
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">2</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">text</span><span style="color: #0000FF;">)-</span><span style="color: #000000;">1</span> <span style="color: #008080;">do</span>
 
<span style="color: #008080;">if</span> <span style="color: #000000;">text</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]=</span><span style="color: #008000;">'X'</span>
constant p1 = {2,3,4,5,1}, -- easier than playing with mod(+1,5)
<span style="color: #008080;">and</span> <span style="color: #0000FF;">((</span><span style="color: #000000;">text</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]=</span><span style="color: #008000;">' '</span> <span style="color: #008080;">and</span> <span style="color: #000000;">text</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">-</span><span style="color: #000000;">2</span><span style="color: #0000FF;">]=</span><span style="color: #000000;">text</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">])</span> <span style="color: #008080;">or</span>
m1 = {5,1,2,3,4} -- "" mod(-1,5)
<span style="color: #0000FF;">(</span><span style="color: #000000;">text</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]=</span><span style="color: #008000;">' '</span> <span style="color: #008080;">and</span> <span style="color: #000000;">text</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]=</span><span style="color: #000000;">text</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">+</span><span style="color: #000000;">2</span><span style="color: #0000FF;">]))</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">text</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">'_'</span>
function encode(string plaintext)
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
return playfair(clean_text(plaintext),2,p1)
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
end function
<span style="color: #008080;">return</span> <span style="color: #000000;">text</span>
 
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
function decode(string ciphertext)
-- ciphertext includes spaces we need to skip, hence by 3
<span style="color: #008080;">function</span> <span style="color: #000000;">playfair</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">text</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">integer</span> <span style="color: #000000;">step</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">sequence</span> <span style="color: #000000;">d</span><span style="color: #0000FF;">)</span>
return remove_x(playfair(ciphertext,3,m1))
<span style="color: #000080;font-style:italic;">--
end function
-- text may be the plaintext or the encoded version
-- step is 2 for plaintext, 3 for encoded(/skip spaces)
string keyword = "Playfair example"
-- d is {2,3,4,5,1} instead of mod(+1,5), or
build_table(keyword,'Q')
-- {5,1,2,3,4} -- -1
printf(1,"Playfair keyword : %s\n",{keyword})
--</span>
printf(1,"Option: J=I or no Q (J/Q) : %s\n",pfo)
<span style="color: #004080;">string</span> <span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">""</span>
printf(1,"The table to be used is :\n\n%s\n\n",{join(table,"\n")})
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">text</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">by</span> <span style="color: #000000;">step</span> <span style="color: #008080;">do</span>
string plaintext = "Hide the gold...in the TREESTUMP!!!!",
<span style="color: #004080;">integer</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">row1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">col1</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">findchar</span><span style="color: #0000FF;">[</span><span style="color: #000000;">text</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]-</span><span style="color: #008000;">'A'</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">],</span>
encoded = encode(plaintext),
<span style="color: #0000FF;">{</span><span style="color: #000000;">row2</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">col2</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">findchar</span><span style="color: #0000FF;">[</span><span style="color: #000000;">text</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]-</span><span style="color: #008000;">'A'</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span>
decoded = decode(encoded)
<span style="color: #008080;">if</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">></span><span style="color: #000000;">1</span> <span style="color: #008080;">then</span> <span style="color: #000000;">res</span> <span style="color: #0000FF;">&=</span> <span style="color: #008000;">" "</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
printf(1,"The plain text : %s\n\n",{plaintext})
<span style="color: #008080;">if</span> <span style="color: #000000;">row1</span><span style="color: #0000FF;">=</span><span style="color: #000000;">row2</span> <span style="color: #008080;">then</span>
printf(1,"Encoded text is : %s\n",{encoded})
<span style="color: #0000FF;">{</span><span style="color: #000000;">col1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">col2</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">d</span><span style="color: #0000FF;">[</span><span style="color: #000000;">col1</span><span style="color: #0000FF;">],</span><span style="color: #000000;">d</span><span style="color: #0000FF;">[</span><span style="color: #000000;">col2</span><span style="color: #0000FF;">]}</span>
printf(1,"Decoded text is : %s\n",{decoded})</lang>
<span style="color: #008080;">elsif</span> <span style="color: #000000;">col1</span><span style="color: #0000FF;">=</span><span style="color: #000000;">col2</span> <span style="color: #008080;">then</span>
<span style="color: #0000FF;">{</span><span style="color: #000000;">row1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">row2</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">d</span><span style="color: #0000FF;">[</span><span style="color: #000000;">row1</span><span style="color: #0000FF;">],</span><span style="color: #000000;">d</span><span style="color: #0000FF;">[</span><span style="color: #000000;">row2</span><span style="color: #0000FF;">]}</span>
<span style="color: #008080;">else</span>
<span style="color: #0000FF;">{</span><span style="color: #000000;">col1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">col2</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">col2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">col1</span><span style="color: #0000FF;">}</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #000000;">res</span> <span style="color: #0000FF;">&=</span> <span style="color: #000000;">table</span><span style="color: #0000FF;">[</span><span style="color: #000000;">row1</span><span style="color: #0000FF;">][</span><span style="color: #000000;">col1</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">&</span> <span style="color: #000000;">table</span><span style="color: #0000FF;">[</span><span style="color: #000000;">row2</span><span style="color: #0000FF;">][</span><span style="color: #000000;">col2</span><span style="color: #0000FF;">]</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">res</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">encode</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">plaintext</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">playfair</span><span style="color: #0000FF;">(</span><span style="color: #000000;">clean_text</span><span style="color: #0000FF;">(</span><span style="color: #000000;">plaintext</span><span style="color: #0000FF;">),</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">3</span><span style="color: #0000FF;">,</span><span style="color: #000000;">4</span><span style="color: #0000FF;">,</span><span style="color: #000000;">5</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">})</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">decode</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">ciphertext</span><span style="color: #0000FF;">)</span>
<span style="color: #000080;font-style:italic;">-- ciphertext includes spaces we need to skip, hence by 3</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">remove_x</span><span style="color: #0000FF;">(</span><span style="color: #000000;">playfair</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ciphertext</span><span style="color: #0000FF;">,</span><span style="color: #000000;">3</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">5</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">3</span><span style="color: #0000FF;">,</span><span style="color: #000000;">4</span><span style="color: #0000FF;">}))</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"Playfair keyword : %s\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">keyword</span><span style="color: #0000FF;">})</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"Option: J=I or no Q (J/Q) : %s\n"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">option</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"The table to be used is :\n\n%s\n\n"</span><span style="color: #0000FF;">,{</span><span style="color: #7060A8;">join</span><span style="color: #0000FF;">(</span><span style="color: #000000;">table</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"\n"</span><span style="color: #0000FF;">)})</span>
<span style="color: #004080;">string</span> <span style="color: #000000;">plaintext</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"Hide the gold...in the TREESTUMP!!!!"</span><span style="color: #0000FF;">,</span>
<span style="color: #000000;">encoded</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">encode</span><span style="color: #0000FF;">(</span><span style="color: #000000;">plaintext</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">decoded</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">decode</span><span style="color: #0000FF;">(</span><span style="color: #000000;">encoded</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"The plain text : %s\n\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">plaintext</span><span style="color: #0000FF;">})</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"Encoded text is : %s\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">encoded</span><span style="color: #0000FF;">})</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"Decoded text is : %s\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">decoded</span><span style="color: #0000FF;">})</span>
<!--</syntaxhighlight>-->
{{out}}
<pre>
Line 1,940 ⟶ 2,302:
Decoded text is : HI DE TH EG OL DI NT HE TR E_ ES TU MP
</pre>
The only difference when option is 'J' is the 4<small><sup>th</sup></small> line of table is KNOQS
 
=={{header|Python}}==
{{trans|Raku}}
<langsyntaxhighlight lang="python">from string import ascii_uppercase
from itertools import product
from re import findall
Line 2,004 ⟶ 2,367:
enc = encode(orig)
print "Encoded:", enc
print "Decoded:", decode(enc)</langsyntaxhighlight>
{{out}}
<pre>Original: Hide the gold in...the TREESTUMP!!!
Line 2,012 ⟶ 2,375:
=={{header|Raku}}==
(formerly Perl 6)
<syntaxhighlight lang="raku" line># Instantiate a specific encoder/decoder.
{{Works with|rakudo|2016.07}}
<lang perl6># Instantiate a specific encoder/decoder.
 
sub playfair( $key,
Line 2,056 ⟶ 2,418:
 
return
anon sub enc($red) {
my @list = canon($red).comb(/(.) (.?) <?{ $1 ne $0 }>/);
~@list.map: { .chars == 1 ?? %ENC{$_~'X'} !! %ENC{$_} }
},
anon sub dec($black) {
my @list = canon($black).comb(/../);
~@list.map: { %DEC{$_} }
Line 2,075 ⟶ 2,437:
 
my $red = decode $black;
say " red:\t$red";</langsyntaxhighlight>
{{out}}
<pre> orig: Hide the gold in...the TREESTUMP!!!
Line 2,083 ⟶ 2,445:
=={{header|REXX}}==
Quite a bit of the REXX code deals with error checking, accepting arguments, and displaying the options used, and displaying input and output.
 
<br>For ease of viewing and comparing, the output is in capitalized digraphs (which are really ''digrams'') as well as the original input(s).
For ease of viewing and comparing, the output is in capitalized digraphs (which are really ''digrams'') as well as the original input(s).
<br>Thanks to Walter Pachl, this program is now sensitive of using a suitable ''double character'' when &nbsp; '''X''' &nbsp; is present in the cipher key.
 
Thanks to Walter Pachl, this program is now sensitive of using a suitable ''double character'' when &nbsp; '''X''' &nbsp; is present in the cipher key.
<br>Also, more thanks are due to Walter Pachl for finding that the cipher key can't contain the OMIT character.
 
<br>A fair amount of code was added to massage the decrypted encryption to remove doubled &nbsp; '''X'''es &nbsp; so as to match the original text
A fair amount of code was added to massage the decrypted encryption to remove doubled &nbsp; '''X'''es &nbsp; so as to match the original text
<br>(this is the ''possible text'' part of the REXX code).
<br>(this is the &nbsp; &nbsp; ''possible text'' &nbsp; &nbsp; part of the REXX code).
<lang rexx>/*REXX program implements a PLAYFAIR cipher (encryption and decryption). */
<syntaxhighlight lang="rexx">/*REXX program implements a PLAYFAIR cipher (encryption and decryption). */
@abc= 'abcdefghijklmnopqrstuvwxyz'; @abcU= @abc /*literals for lower and upper ABC's.*/
parse arg omit key '(' text /*TEXT is the phrase to be used. */
Line 2,097 ⟶ 2,462:
if omit=='' | omit==',' then omit= 'J' /*the "omitted" character string. */
if text='' then text= 'Hide the gold in the tree stump!!' /*default.*/
upper omit @abcU /*uppercase OMIT characters & alphabet.*/
@cant= 'can''t contain the "OMIT" character: ' omit /*literal used in error text.*/
@uchars= 'unique characters.' /*a literal used below in an error msg.*/
newKey = scrub(key, 1) /*scrub old cipher key ──► newKey */
newText= scrub(text ) /* " " text ──► newText */
Line 2,102 ⟶ 2,470:
if length(omit)\==1 then call err 'OMIT letter must be only one letter.'
if \datatype(omit, 'M') then call err 'OMIT letter must be a Latin alphabet letter.'
upper omit @abcU /*uppercase OMIT characters & alphabet.*/
@cant= 'can''t contain the "OMIT" character: ' omit /*literal used in error text*/
if pos(omit, newText)\==0 then call err 'TEXT' @cant
if pos(omit, newKey) \==0 then call err 'cipher key' @cant
Line 2,109 ⟶ 2,475:
xx= 'X' /*character used for double characters.*/
if omit==xx then xx= 'Q' /* " " " " " */
if length(newKey)<3 then call err 'cipher key is too short, must be ≥ 3' @uchars
'cipher key is too short, must be ≥ 3 unique characters.'
fill= space( translate(fill, , newKey), 0) /*remove any cipher characters. */
grid= newKey || fill /*only first 25 characters are used. */
Line 2,120 ⟶ 2,485:
padL= 14 + 2
call show 'cleansed', newText
#=0 0 /*number of grid characters used. */
do row =1 for 5 /*build array of individual cells. */
do col=1 for 5; #= # + 1; @.row.col= substr(grid, #, 1)
Line 2,149 ⟶ 2,514:
show: arg ,y; say; say right(arg(1) 'text: ',padL) digram(y); say pad space(y, 0); return
/*──────────────────────────────────────────────────────────────────────────────────────*/
.Playfair: arg T,encrypt; i= -1; if encrypt==1 then i= 1; $=
do k=1 while i==1; _= substr(T, k, 1); if _==' ' then leave
if _==substr(T, k+1, 1) then T= left(T, k) || Lxx || substr(T, k + 1)
end /*k*/
upper T
do j=1 by 2 to length(T); __= strip( substr(T, j, 2) )
if LR()==1 then __= __ || xx; call LR /*append X or Q char, rule 1*/
select /*rule*/
when rowL==rowR then __= @@(rowL, colL+i)@@(rowR, colR+i) /*rule 2*/
when colL==colR then __= @@(rowL+i, colL )@@(rowR+i, colR) /*rule 3*/
otherwise __= @@(rowL, colR )@@(rowR, colL) /*rule 4*/
end /*select*/
$= $ || __
end /*j*/
return $
/*──────────────────────────────────────────────────────────────────────────────────────*/
digram: procedure; parse arg x,,$; $=; do j=1 by 2 to length(x)
$= $ || substr(x, j, 2)' '
end /*j*/
return strip($)
/*──────────────────────────────────────────────────────────────────────────────────────*/
Line 2,173 ⟶ 2,538:
$=; do j=1 for length(xxx); _= substr(xxx, j, 1)
if unique==1 then if pos(_, $)\==0 then iterate /*is unique?*/
if datatype(_, 'M') then $= $ || _ _ /*only use Latin letters. */
end /*j*/
return $</langsyntaxhighlight>
Some older REXXes don't have a '''changestr''' bif, so one is included here ──► [[CHANGESTR.REX]].
<br><br>
Line 2,224 ⟶ 2,589:
════════════════Playfair encryption──► decryption──► encryption worked.
</pre>
 
=={{header|Ruby}}==
Printing the cipher in pairs just advertises the mechanism of encoding; I've gone with the traditional grouping into sequences of five letters instead.
 
<syntaxhighlight lang="ruby">class Playfair
Size = 5
def initialize(key, missing)
@missing = missing.upcase
alphabet = ('A'..'Z').to_a.join.upcase.delete(@missing).split''
extended = key.upcase.gsub(/[^A-Z]/,'').split('') + alphabet
grid = extended.uniq[0...Size*Size].each_slice(Size).to_a
coords = {}
grid.each_with_index do |row, i|
row.each_with_index do |letter, j|
coords[letter] = [i,j]
end
end
@encode = {}
alphabet.product(alphabet).reject { |a,b| a==b }.each do |a, b|
i1, j1 = coords[a]
i2, j2 = coords[b]
if i1 == i2 then
j1 = (j1 + 1) % Size
j2 = (j2 + 1) % Size
elsif j1 == j2 then
i1 = (i1 + 1) % Size
i2 = (i2 + 1) % Size
else
j1, j2 = j2, j1
end
@encode["#{a}#{b}"] = "#{grid[i1][j1]}#{grid[i2][j2]}"
@decode = @encode.invert
end
end
 
def encode(plaintext)
plain = plaintext.upcase.gsub(/[^A-Z]/,'')
if @missing == 'J' then
plain = plain.gsub(/J/, 'I')
else
plain = plain.gsub(@missing, 'X')
end
plain = plain.gsub(/(.)\1/, '\1X\1')
if plain.length % 2 == 1 then
plain += 'X'
end
return plain.upcase.split('').each_slice(2).map do |pair|
@encode[pair.join]
end.join.split('').each_slice(5).map{|s|s.join}.join(' ')
end
 
def decode(ciphertext)
cipher = ciphertext.upcase.gsub(/[^A-Z]/,'')
return cipher.upcase.split('').each_slice(2).map do |pair|
@decode[pair.join]
end.join.split('').each_slice(5).map{|s|s.join}.join(' ')
end
end</syntaxhighlight>
 
{{Out}}
<pre>irb(main):001:0> cipher = (p=Playfair.new 'Playfair example','J').encode('hide the gold in the tree stump')
=> "BMODZ BXDNA BEKUD MUIXM MOUVI F"
irb(main):002:0> p.decode(cipher)
=> "HIDET HEGOL DINTH ETREX ESTUM P"</pre>
 
=={{header|Sidef}}==
{{trans|Perl 6Raku}}
<langsyntaxhighlight lang="ruby">func playfair(key, from = 'J', to = (from == 'J' ? 'I' : '')) {
 
func canon(str) {
Line 2,285 ⟶ 2,714:
 
var red = decode(black)
say " red:\t#{red}"</langsyntaxhighlight>
{{out}}
<pre>
Line 2,294 ⟶ 2,723:
 
=={{header|SQL}}==
<langsyntaxhighlight lang="sql">
--Clean up previous run
IF EXISTS (SELECT *
Line 2,608 ⟶ 3,037:
WHERE NAME = 'FairPlayTable')
DROP TYPE FAIRPLAYTABLE
</syntaxhighlight>
</lang>
 
=={{header|Tcl}}==
{{incorrect|Tcl|TREESTUMP -> TREXSTUMPZ, should be TREXESTUMP}}
(My guess is that lappend digraphs $c0 [expr {$c0 eq $c ? "X" : $c}] is simply discarding $c. [[User:Petelomax|Pete Lomax]] ([[User talk:Petelomax|talk]]) 05:54, 13 October 2018 (UTC))
 
{{works with|Tcl|8.6}}
<langsyntaxhighlight lang="tcl">package require TclOO
 
oo::class create Playfair {
variable grid lookup excluder
constructor {{keyword "PLAYFAIR EXAMPLE"} {exclude "J"}} {
# Tweaking according to exact operation mode
if {$exclude eq "J"} {
set excluder "J I"
} else {
set excluder [list $exclude ""]
}
}
# Clean up the keyword source
set keys [my Clean [append keyword "ABCDEFGHIJKLMNOPQRSTUVWXYZ"]]
# Generate the encoding grid
set grid [lrepeat 5 [lrepeat 5 ""]]
set idx -1
for {set i 0} {$i < 5} {incr i} {for {set j 0} {$j < 5} {} {
if {![info exist lookup([set c [lindex $keys [incr idx]]])]} {
lset grid $i $j $c
set lookup($c) [list $i $j]
incr j
}
}}
 
# Sanity check
# Clean up the keyword source
if {[array size lookup] != 25} {
set keys [my Clean [append keyword "ABCDEFGHIJKLMNOPQRSTUVWXYZ"]]
error "failed to build encoding table correctly"
 
}
# Generate the encoding grid
set grid [lrepeat 5 [lrepeat 5 ""]]
set idx -1
for {set i 0} {$i < 5} {incr i} {for {set j 0} {$j < 5} {} {
if {![info exist lookup([set c [lindex $keys [incr idx]]])]} {
lset grid $i $j $c
set lookup($c) [list $i $j]
incr j
}
}}
 
# Sanity check
if {[array size lookup] != 25} {
error "failed to build encoding table correctly"
}
}
 
# Worker to apply a consistent cleanup/split rule
method Clean {str} {
set str [string map $excluder [string toupper $str]]
split [regsub -all {[^A-Z]} $str ""] ""
}
 
# These public methods are implemented by a single non-public method
forward encode my Transform 1
forward decode my Transform -1
 
# The application of the Playfair cypher transform
method Transform {direction message} {
# Split message into true digraphs
foreach c [my Clean $message] {
if {![info exists lookup($c)]} continue
if {![info existexists c0]} {
set c0 $c
lappend digraphs $c0 [expr {$c0 eq $c ? "X" : $c}]
} else {
unset c0
} else if {$c0 ne $c} {
lappend digraphs $c0 $c
set c0 $c
unset c0
}
} else {
}
lappend digraphs $c0 "X"
if {[info exist c0]} {
set c0 $c
lappend digraphs $c0 "Z"
}
}
}
}
if {[info exists c0]} {
lappend digraphs $c0 "Z"
}
 
# Encode the digraphs
set result ""
foreach {a b} $digraphs {
lassign $lookup($a) ai aj
lassign $lookup($b) bi bj
if {$ai == $bi} {
set aj [expr {($aj + $direction) % 5}]
set bj [expr {($bj + $direction) % 5}]
} elseif {$aj == $bj} {
set ai [expr {($ai + $direction) % 5}]
set bi [expr {($bi + $direction) % 5}]
} else {
set tmp $aj
set aj $bj
set bj $tmp
}
lappend result [lindex $grid $ai $aj][lindex $grid $bi $bj]
}
}
 
# Real use would be: return [join $result ""]
return $result
}
}</langsyntaxhighlight>
Demonstrating:
<langsyntaxhighlight lang="tcl">Playfair create cypher "Playfair Example"
set plaintext "Hide the gold in...the TREESTUMP!!!"
set encoded [cypher encode $plaintext]
Line 2,703 ⟶ 3,135:
puts "Original: $plaintext"
puts "Encoded: $encoded"
puts "Decoded: $decoded"</langsyntaxhighlight>
{{out}}
<pre>
Original: Hide the gold in...the TREESTUMP!!!
Encoded: BM OD ZB XD NA BE KU DM UI XM KZMO ZRUV FTIF
Decoded: HI DE TH EG OL DI NT HE TR EX STES UMTU PZMP
</pre>
 
=={{header|VBA}}==
<syntaxhighlight lang="vb">
<lang vb>
Option Explicit
 
Line 2,919 ⟶ 3,351:
SwapPairsDecoding = myTable(resD1.Row, resD1.Column) & myTable(resD2.Row, resD2.Column)
End Select
End Function</langsyntaxhighlight>
{{out}}
<pre>Enter your keyword : Playfair example
Line 2,942 ⟶ 3,374:
Encoded text is : BM OD ZB XD NA BE KU DM UI XM MO UV IF
Decoded text is : HI DE TH EG OL DI NT HE TR EE ST UM PX</pre>
 
=={{header|V (Vlang)}}==
{{trans|Go}}
<syntaxhighlight lang="v (vlang)">import os
import strings
type PlayfairOption = int
const (
no_q = 0
i_equals_j = 1
)
struct Playfair {
mut:
keyword string
pfo PlayfairOption
table [5][5]u8
}
fn (mut p Playfair) init() {
// Build table.
mut used := [26]bool{} // all elements false
if p.pfo == no_q {
used[16] = true // Q used
} else {
used[9] = true // J used
}
alphabet := p.keyword.to_upper() + "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
for i, j, k := 0, 0, 0; k < alphabet.len; k++ {
c := alphabet[k]
if c < 'A'[0] || c > 'Z'[0] {
continue
}
d := int(c - 65)
if !used[d] {
p.table[i][j] = c
used[d] = true
j++
if j == 5 {
i++
if i == 5 {
break // table has been filled
}
j = 0
}
}
}
}
fn (p Playfair) get_clean_text(pt string) string {
// Ensure everything is upper case.
plain_text := pt.to_upper()
// Get rid of any non-letters and insert X between duplicate letters.
mut clean_text := strings.new_builder(128)
// Safe to assume null u8 won't be present in plain_text.
mut prev_byte := `\000`
for i in 0..plain_text.len {
mut next_byte := plain_text[i]
// It appears that Q should be omitted altogether if NO_Q option is specified;
// we assume so anyway.
if next_byte < 'A'[0] || next_byte > 'Z'[0] || (next_byte == 'Q'[0] && p.pfo == no_q) {
continue
}
// If i_equals_j option specified, replace J with I.
if next_byte == 'J'[0] && p.pfo == i_equals_j {
next_byte = 'I'[0]
}
if next_byte != prev_byte {
clean_text.write_u8(next_byte)
} else {
clean_text.write_u8('X'[0])
clean_text.write_u8(next_byte)
}
prev_byte = next_byte
}
l := clean_text.len
if l%2 == 1 {
// Dangling letter at end so add another letter to complete digram.
if clean_text.str()[l-1] != 'X'[0] {
clean_text.write_u8('X'[0])
} else {
clean_text.write_u8('Z'[0])
}
}
return clean_text.str()
}
fn (p Playfair) find_byte(c u8) (int, int) {
for i in 0..5 {
for j in 0..5 {
if p.table[i][j] == c {
return i, j
}
}
}
return -1, -1
}
fn (p Playfair) encode(plain_text string) string {
clean_text := p.get_clean_text(plain_text)
mut cipher_text := strings.new_builder(128)
l := clean_text.len
for i := 0; i < l; i += 2 {
row1, col1 := p.find_byte(clean_text[i])
row2, col2 := p.find_byte(clean_text[i+1])
if row1 == row2{
cipher_text.write_u8(p.table[row1][(col1+1)%5])
cipher_text.write_u8(p.table[row2][(col2+1)%5])
} else if col1 == col2{
cipher_text.write_u8(p.table[(row1+1)%5][col1])
cipher_text.write_u8(p.table[(row2+1)%5][col2])
} else {
cipher_text.write_u8(p.table[row1][col2])
cipher_text.write_u8(p.table[row2][col1])
}
if i < l-1 {
cipher_text.write_u8(' '[0])
}
}
return cipher_text.str()
}
fn (p Playfair) decode(cipher_text string) string {
mut decoded_text := strings.new_builder(128)
l := cipher_text.len
// cipher_text will include spaces so we need to skip them.
for i := 0; i < l; i += 3 {
row1, col1 := p.find_byte(cipher_text[i])
row2, col2 := p.find_byte(cipher_text[i+1])
if row1 == row2 {
mut temp := 4
if col1 > 0 {
temp = col1 - 1
}
decoded_text.write_u8(p.table[row1][temp])
temp = 4
if col2 > 0 {
temp = col2 - 1
}
decoded_text.write_u8(p.table[row2][temp])
} else if col1 == col2 {
mut temp := 4
if row1 > 0 {
temp = row1 - 1
}
decoded_text.write_u8(p.table[temp][col1])
temp = 4
if row2 > 0 {
temp = row2 - 1
}
decoded_text.write_u8(p.table[temp][col2])
} else {
decoded_text.write_u8(p.table[row1][col2])
decoded_text.write_u8(p.table[row2][col1])
}
if i < l-1 {
decoded_text.write_u8(' '[0])
}
}
return decoded_text.str()
}
fn (p Playfair) print_table() {
println("The table to be used is :\n")
for i in 0..5 {
for j in 0..5 {
print("${p.table[i][j].ascii_str()} ")
}
println('')
}
}
fn main() {
keyword := os.input("Enter Playfair keyword : ")
mut ignore_q := ''
for ignore_q != "y" && ignore_q != "n" {
ignore_q = os.input("Ignore Q when building table y/n : ").to_lower()
}
mut pfo := no_q
if ignore_q == "n" {
pfo = i_equals_j
}
mut table := [5][5]u8{}
mut pf := Playfair{keyword, pfo, table}
pf.init()
pf.print_table()
plain_text := os.input("\nEnter plain text : ")
encoded_text := pf.encode(plain_text)
println("\nEncoded text is : $encoded_text")
decoded_text := pf.decode(encoded_text)
println("Deccoded text is : $decoded_text")
}</syntaxhighlight>
 
{{out}}
Sample run:
<pre>
Enter Playfair keyword : Playfair example
Ignore Q when building table y/n : n
The table to be used is :
 
P L A Y F
I R E X M
B C D G H
K N O Q S
T U V W Z
 
Enter plain text : Hide the gold...in the TREESTUMP!!!!
 
Encoded text is : BM OD ZB XD NA BE KU DM UI XM MO UV IF
Deccoded text is : HI DE TH EG OL DI NT HE TR EX ES TU MP
</pre>
 
=={{header|Wren}}==
{{trans|Kotlin}}
{{libheader|Wren-dynamic}}
{{libheader|Wren-str}}
{{libheader|Wren-iterate}}
{{libheader|Wren-ioutil}}
<syntaxhighlight lang="wren">import "./dynamic" for Enum
import "./str" for Str, Char
import "./iterate" for Stepped
import "./ioutil" for Input
 
var PlayfairOption = Enum.create("PlayfairOption", ["NO_Q", "I_EQUALS_J"])
 
class Playfair {
construct new(keyword, pfo) {
_pfo = pfo
// build_table
_table = List.filled(5, null)
for (i in 0..4) _table[i] = List.filled(5, "\0") // 5 * 5 char list
var used = List.filled(26, false)
if (_pfo == PlayfairOption.NO_Q) {
used[16] = true // Q used
} else {
used[9] = true // J used
}
var alphabet = Str.upper(keyword) + "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
var i = 0
var j = 0
for (k in 0...alphabet.count) {
var c = alphabet[k]
if (Char.isAsciiUpper(c)) {
var d = c.bytes[0] - 65
if (!used[d]) {
_table[i][j] = c
used[d] = true
j = j + 1
if (j == 5) {
i = i + 1
if (i == 5) break // table has been filled
j = 0
}
}
}
}
}
 
getCleanText_(plainText) {
var plainText2 = Str.upper(plainText) // ensure everything is upper case
// get rid of any non-letters and insert X between duplicate letters
var cleanText = ""
var prevChar = "\0" // safe to assume null character won't be present in plainText
for (i in 0...plainText2.count) {
var nextChar = plainText2[i]
// It appears that Q should be omitted altogether if NO_Q option is specified - we assume so anyway
if (Char.isAsciiUpper(nextChar) && (nextChar != "Q" || _pfo != PlayfairOption.NO_Q)) {
// If I_EQUALS_J option specified, replace J with I
if (nextChar == "J" && _pfo == PlayfairOption.I_EQUALS_J) nextChar = "I"
if (nextChar != prevChar) {
cleanText = cleanText + nextChar
} else {
cleanText = cleanText + "X" + nextChar
}
prevChar = nextChar
}
}
var len = cleanText.count
if (len % 2 == 1) { // dangling letter at end so add another letter to complete digram
if (cleanText[-1] != "X") {
cleanText = cleanText + "X"
} else {
cleanText = cleanText + "Z"
}
}
return cleanText
}
 
findChar_(c) {
for (i in 0..4) {
for (j in 0..4) if (_table[i][j] == c) return [i, j]
}
return [-1, -1]
}
 
encode(plainText) {
var cleanText = getCleanText_(plainText)
var cipherText = ""
var length = cleanText.count
for (i in Stepped.new(0...length, 2)) {
var pair = findChar_(cleanText[i])
var row1 = pair[0]
var col1 = pair[1]
pair = findChar_(cleanText[i + 1])
var row2 = pair[0]
var col2 = pair[1]
cipherText = cipherText +
((row1 == row2) ? _table[row1][(col1 + 1) % 5] +_table[row2][(col2 + 1) % 5] :
(col1 == col2) ? _table[(row1 + 1) % 5][col1] +_table[(row2 + 1) % 5][col2] :
_table[row1][col2] +_table[row2][col1])
if (i < length - 1) cipherText = cipherText + " "
}
return cipherText
}
 
decode(cipherText) {
var decodedText = ""
var length = cipherText.count
for (i in Stepped.new(0...length, 3)) { // cipherText will include spaces so we need to skip them
var pair = findChar_(cipherText[i])
var row1 = pair[0]
var col1 = pair[1]
pair = findChar_(cipherText[i + 1])
var row2 = pair[0]
var col2 = pair[1]
decodedText = decodedText +
((row1 == row2) ? _table[row1][(col1 > 0) ? col1-1 : 4] +_table[row2][(col2 > 0) ? col2-1 : 4] :
(col1 == col2) ? _table[(row1 > 0) ? row1-1 : 4][col1] +_table[(row2 > 0) ? row2-1 : 4][col2] :
_table[row1][col2] +_table[row2][col1])
if (i < length - 1) decodedText = decodedText + " "
}
return decodedText
}
 
printTable() {
System.print("The_table to be used is :\n")
for (i in 0..4) {
for (j in 0..4) System.write(_table[i][j] + " ")
System.print()
}
}
}
 
var keyword = Input.text("Enter Playfair keyword : ", 1)
var ignoreQ = Str.lower(Input.option("Ignore Q when building_table y/n : ", "yYnN"))
var pfo = (ignoreQ == "y") ? PlayfairOption.NO_Q : PlayfairOption.I_EQUALS_J
var playfair = Playfair.new(keyword, pfo)
playfair.printTable()
var plainText = Input.text("\nEnter plain text : ")
var encodedText = playfair.encode(plainText)
System.print("\nEncoded text is : %(encodedText)")
var decodedText = playfair.decode(encodedText)
System.print("Decoded text is : %(decodedText)")</syntaxhighlight>
 
{{out}}
<pre>
Enter Playfair keyword : Playfair example
Ignore Q when building_table y/n : n
The_table to be used is :
 
P L A Y F
I R E X M
B C D G H
K N O Q S
T U V W Z
 
Enter plain text : Hide the gold...in the TREESTUMP!!!!
 
Encoded text is : BM OD ZB XD NA BE KU DM UI XM MO UV IF
Decoded text is : HI DE TH EG OL DI NT HE TR EX ES TU MP
</pre>
 
=={{header|zkl}}==
<langsyntaxhighlight lang="zkl">fcn genKeyTable(key,deadChr){ // deadChr=="Q" or "J"
deadChr=deadChr.toUpper();
key=key.toUpper().unique() - " " - deadChr;
return(key + (["A".."Z"].pump(String) - deadChr - key), deadChr);
}</langsyntaxhighlight>
<langsyntaxhighlight lang="zkl">fcn playfair(text,keytable){ // text is a-z only
keyTable,deadChr:=keytable;
text=text.toUpper();
Line 2,972 ⟶ 3,775:
})
.pump(String,Void.Read,"".create.fp(" ")).strip(); // insert blanks
}</langsyntaxhighlight>
<langsyntaxhighlight lang="zkl">fcn decodePF(text,keyTable){
keyTable,_=keyTable;
text-=" ";
Line 2,989 ⟶ 3,792:
.pump(String,Void.Read,"".create.fp(" ")).strip(); // insert blanks
}
</syntaxhighlight>
</lang>
<langsyntaxhighlight lang="zkl">msg:="Hide the gold in the tree stump!!!";
keyTable:=genKeyTable("playfair example");
msg.println();
e:=playfair(msg,keyTable); e.println();
decodePF(e,keyTable).println();
playfair("XX",keyTable).println() : decodePF(_,keyTable).println();</langsyntaxhighlight>
{{out}}
<pre>
9,482

edits