78 lines
2.1 KiB
APL
78 lines
2.1 KiB
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
|