Playfair cipher: Difference between revisions

m
m (added highlighting.)
m (→‎{{header|Wren}}: Minor tidy)
 
(13 intermediate revisions by 11 users not shown)
Line 15:
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 126 ⟶ 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 150 ⟶ 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 220 ⟶ 382:
writeln(" Encoded: ", enc);
writeln(" Decoded: ", pf.decode(enc));
}</langsyntaxhighlight>
{{out}}
<pre>Original: Hide the gold in...the TREESTUMP!!!
Line 227 ⟶ 389:
 
=={{header|FreeBASIC}}==
<langsyntaxhighlight lang="freebasic">' FB 1.05.0 Win64
 
Enum PlayFairOption
Line 382 ⟶ 544:
Print
Print "Press any key to quit"
Sleep</langsyntaxhighlight>
Sample input/output:
{{out}}
Line 404 ⟶ 566:
=={{header|Go}}==
{{trans|Kotlin}}
<langsyntaxhighlight lang="go">package main
 
import (
Line 611 ⟶ 773:
decodedText := pf.decode(encodedText)
fmt.Println("Deccoded text is :", decodedText)
}</langsyntaxhighlight>
 
{{out}}
Line 635 ⟶ 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 737 ⟶ 899:
| odd (length str) = str ++ "x"
| otherwise = str
</syntaxhighlight>
</lang>
 
<pre>
Line 751 ⟶ 913:
 
'''Implementation:'''
<langsyntaxhighlight Jlang="j">choose=: verb define
sel=. 'Q' e. y
alph=: (sel { 'JQ') -.~ a. {~ 65 + i.26
Line 785 ⟶ 947:
decrypt=: verb define
;:inv ;/, ref{~alt i. pairs y
)</langsyntaxhighlight>
 
'''Example use:'''
<langsyntaxhighlight Jlang="j"> choose 'IJ'
 
setkey 'playfair example'
Line 795 ⟶ 957:
BM OD ZB XD NA BE KU DM UI XM MO UV IF
decrypt 'BM OD ZB XD NA BE KU DM UI XM MO UV IF'
HIDETHEGOLDINTHETREXESTUMP</syntaxhighlight>
HI DE TH EG OL DI NT HE TR EX ES TU MP</lang>
 
=={{header|Java}}==
<langsyntaxhighlight lang="java">import java.awt.Point;
import java.util.Scanner;
 
Line 901 ⟶ 1,063:
return text.toString();
}
}</langsyntaxhighlight>
 
=== alternative version ===
 
<langsyntaxhighlight lang="java">import java.util.Scanner;
public class PlayfairCipherEncryption
Line 1,109 ⟶ 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,172 ⟶ 1,334:
 
println("Decoded: ", playfair("Playfair example", encoded, false))
</langsyntaxhighlight>{{out}}
<pre>
Original: Hide the gold in...the TREESTUMP!!!
Line 1,181 ⟶ 1,343:
=={{header|Kotlin}}==
{{trans|FreeBASIC}}
<langsyntaxhighlight lang="scala">// version 1.0.5-2
 
enum class PlayfairOption {
Line 1,313 ⟶ 1,475:
val decodedText = playfair.decode(encodedText)
println("Decoded text is : $decodedText")
}</langsyntaxhighlight>
 
{{out}}
Line 1,332 ⟶ 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}}
<langsyntaxhighlight Nimlang="nim">import pegs, strutils
 
type
Line 1,433 ⟶ 1,672:
 
echo "Encoded message: ", enc
echo "Decoded message: ", dec</langsyntaxhighlight>
 
{{out}}
Line 1,443 ⟶ 1,682:
 
=={{header|NetRexx}}==
<langsyntaxhighlight NetRexxlang="netrexx">/* NetRexx */
options replace format comments java crossref symbols nobinary
 
Line 1,608 ⟶ 1,847:
 
return
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 1,631 ⟶ 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,828 ⟶ 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,851 ⟶ 2,090:
=={{header|Perl}}==
{{trans|Raku}}
<langsyntaxhighlight lang="perl">use Math::Cartesian::Product;
 
# Pregenerate all forward and reverse translations
Line 1,922 ⟶ 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,931 ⟶ 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 2,059 ⟶ 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,123 ⟶ 2,367:
enc = encode(orig)
print "Encoded:", enc
print "Decoded:", decode(enc)</langsyntaxhighlight>
{{out}}
<pre>Original: Hide the gold in...the TREESTUMP!!!
Line 2,131 ⟶ 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,175 ⟶ 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,194 ⟶ 2,437:
 
my $red = decode $black;
say " red:\t$red";</langsyntaxhighlight>
{{out}}
<pre> orig: Hide the gold in...the TREESTUMP!!!
Line 2,210 ⟶ 2,453:
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 &nbsp; &nbsp; ''possible text'' &nbsp; &nbsp; part of the REXX code).
<langsyntaxhighlight 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,297 ⟶ 2,540:
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,346 ⟶ 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|Raku}}
<langsyntaxhighlight lang="ruby">func playfair(key, from = 'J', to = (from == 'J' ? 'I' : '')) {
 
func canon(str) {
Line 2,407 ⟶ 2,714:
 
var red = decode(black)
say " red:\t#{red}"</langsyntaxhighlight>
{{out}}
<pre>
Line 2,416 ⟶ 2,723:
 
=={{header|SQL}}==
<langsyntaxhighlight lang="sql">
--Clean up previous run
IF EXISTS (SELECT *
Line 2,730 ⟶ 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,825 ⟶ 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 3,041 ⟶ 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 3,064 ⟶ 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}}==
Line 3,069 ⟶ 3,590:
{{libheader|Wren-dynamic}}
{{libheader|Wren-str}}
{{libheader|Wren-traititerate}}
{{libheader|Wren-ioutil}}
<langsyntaxhighlight ecmascriptlang="wren">import "./dynamic" for Enum
import "./str" for Str, Char
import "./traititerate" for Stepped
import "./ioutil" for Input
 
var PlayfairOption = Enum.create("PlayfairOption", ["NO_Q", "I_EQUALS_J"])
Line 3,205 ⟶ 3,726:
System.print("\nEncoded text is : %(encodedText)")
var decodedText = playfair.decode(encodedText)
System.print("Decoded text is : %(decodedText)")</langsyntaxhighlight>
 
{{out}}
Line 3,226 ⟶ 3,747:
 
=={{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 3,254 ⟶ 3,775:
})
.pump(String,Void.Read,"".create.fp(" ")).strip(); // insert blanks
}</langsyntaxhighlight>
<langsyntaxhighlight lang="zkl">fcn decodePF(text,keyTable){
keyTable,_=keyTable;
text-=" ";
Line 3,271 ⟶ 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,476

edits