RosettaCodeData/Task/Playfair-cipher/APL/playfair-cipher.apl

78 lines
2.1 KiB
APL
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

⍝⍝⍝⍝ 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