Playfair cipher

From Rosetta Code
Playfair cipher is a draft programming task. It is not yet considered ready to be promoted as a complete task, for reasons that should be found in its talk page.

Implement a Playfair cipher encryption and decryption.

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.

C++

<lang cpp>

  1. include <iostream>
  2. include <string>

//-------------------------------------------------------------------------------------------------- using namespace std;

//-------------------------------------------------------------------------------------------------- class playfair { public:

   void doIt( string k, string t, bool ij, bool e )
   {

createGrid( k, ij ); getTextReady( t, ij, e ); if( e ) doIt( 1 ); else doIt( -1 ); display();

   }

private:

   void doIt( int dir )
   {

int a, b, c, d; string ntxt; for( string::iterator ti = _txt.begin(); ti != _txt.end(); ti++ ) { if( getCharPos( ( *ti++ ), a, b ) ) if( getCharPos( ( *ti ), c, d ) ) { if( a == c ) { ntxt.append( getChar( a, b + dir ), 1 ); ntxt.append( getChar( c, d + dir ), 1 ); } else if( b == d ){ ntxt.append( getChar( a + dir, b ), 1 ); ntxt.append( getChar( c + dir, d ), 1 ); } else { ntxt.append( getChar( c, b ), 1 ); ntxt.append( getChar( a, d ), 1 ); } } } _txt = ntxt;

   }
   void display()
   {

cout << "\n\n OUTPUT:\n=========" << endl; string::iterator si = _txt.begin(); int cnt = 0; while( si != _txt.end() ) { cout << ( *si ); si++; cout << ( *si ) << " "; si++; if( ++cnt >= 26 ) cout << endl, cnt = 0; } cout << endl << endl;

   }
   char* getChar( int a, int b )
   {

if( a > 4 ) a = 0; if( b > 4 ) b = 0; if( a < 0 ) a = 4; if( b < 0 ) b = 4; return &_m[a + 5 * b];

   }
   bool getCharPos( char l, int &a, int &b )
   {

for( int y = 0; y < 5; y++ ) { int yy = 5 * y; for( int x = 0; x < 5; x++ ) if( _m[x + yy] == l ) { a = x; b = y; return true; }

} return false;

   }
   void getTextReady( string t, bool ij, bool e )
   {

for( string::iterator si = t.begin(); si != t.end(); si++ ) { ( *si ) = toupper( ( *si ) ); if( ( *si ) < 65 || ( *si ) > 90 ) continue; if( ( *si ) == 'J' && ij ) ( *si ) = 'I'; else if( ( *si ) == 'Q' && !ij ) continue; _txt.append( &( *si ), 1 ); } if( e ) { string ntxt = ""; size_t len = _txt.length(); for( size_t x = 0; x < len; x += 2 ) { ntxt.append( &_txt[x], 1 ); if( x + 1 < len ) { if( _txt[x] == _txt[x + 1] ) ntxt.append( "X" ); ntxt.append( &_txt[x + 1], 1 ); } } _txt = ntxt; } if( _txt.length() & 1 ) _txt.append( "X", 1 );

   }
   void createGrid( string k, bool ij )
   {

if( k.length() < 1 ) k = "KEYWORD"; k.append( "ABCDEFGHIJKLMNOPQRSTUVWXYZ" ); string nk = ""; for( string::iterator si = k.begin(); si != k.end(); si++ ) { ( *si ) = toupper( ( *si ) ); if( ( *si ) < 65 || ( *si ) > 90 ) continue; if( ( ( *si ) == 'J' && ij ) || ( ( *si ) == 'Q' && !ij ) )continue; if( nk.find( ( *si ) ) == -1 ) nk.append( &( *si ), 1 ); } copy( nk.begin(), nk.end(), _m );

   }
   string _txt; char _m[25];

}; //-------------------------------------------------------------------------------------------------- int main( int argc, char* argv[] ) {

   string key, i, txt; bool ij, e;
   cout << "(E)ncode or (D)ecode? "; getline( cin, i ); e = ( i[0] == 'e' || i[0] == 'E' );
   cout << "Enter a en/decryption key: "; getline( cin, key ); 
   cout << "I <-> J (Y/N): "; getline( cin, i ); ij = ( i[0] == 'y' || i[0] == 'Y' );
   cout << "Enter the text: "; getline( cin, txt ); 
   playfair pf; pf.doIt( key, txt, ij, e ); return system( "pause" );

} //-------------------------------------------------------------------------------------------------- </lang>

Output:

(E)ncode or (D)ecode? e Enter a en/decryption key: playfair example I <-> J (Y/N): y Enter the text: Hide the gold in the tree stump

OUTPUT: ========= BM OD ZB XD NA BE KU DM UI XM MO UV IF


(E)ncode or (D)ecode? d Enter a en/decryption key: playfair example I <-> J (Y/N): y Enter the text: BMODZBXDNABEKUDMUIXMMOUVIF

OUTPUT: ========= HI DE TH EG OL DI NT HE TR EX ES TU MP

Perl 6

<lang perl6># Instantiate a specific encoder/decoder.

sub playfair( $key,

             $from = 'J',

$to = $from eq 'J' ?? 'I' !! ) {

   sub canon($str) { $str.subst(/<-alpha>/,, :g).uc.subst(/$from/,$to,:g) }
   # Build 5x5 matrix.
   my @m = canon($key ~ ('A'..'Z').join).comb.uniq.map:

-> $a,$b,$c,$d,$e { [$a,$b,$c,$d,$e] }

   # Pregenerate all forward translations.
   my %ENC = gather {

# Map pairs in same row. for @m -> @r { for ^@r X ^@r -> \i,\j { next if i == j; take @r[i] ~ @r[j] => @r[(i+1)%5] ~ @r[(j+1)%5]; } }

# Map pairs in same column. for ^5 -> $c { my @c = @m.map: *.[$c]; for ^@c X ^@c -> \i,\j { next if i == j; take @c[i] ~ @c[j] => @c[(i+1)%5] ~ @c[(j+1)%5]; } }

# Map pairs with cross-connections. for ^5 X ^5 X ^5 X ^5 -> \i1,\j1,\i2,\j2 { next if i1 == i2 or j1 == j2; take @m[i1][j1] ~ @m[i2][j2] => @m[i1][j2] ~ @m[i2][j1]; }

   }
   # Generate reverse translations.
   my %DEC = %ENC.invert;
   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{$_} } } }

my (&encode,&decode) = playfair 'Playfair example';

my $orig = "Hide the gold in...the TREESTUMP!!!"; say " orig:\t$orig";

my $black = encode $orig; say "black:\t$black";

my $red = decode $black; say " red:\t$red";</lang>

Output:
 orig:	Hide the gold in...the TREESTUMP!!!
black:	BM OD ZB XD NA BE KU DM UI XM MO UV IF
  red:	HI DE TH EG OL DI NT HE TR EX ES TU MP