#!/usr/bin/perl use strict; # https://rosettacode.org/wiki/ADFGVX_cipher use warnings; use List::Util qw( shuffle ); my $plaintext = 'ATTACKAT1200AM'; my $keysize = 9; my $polybius = < =~ /^.{$keysize}$/gm }; my ($n, @deorder) = 0; my @reorder = map /.(.+)/, sort map $_ . $n++, split //, $keyword; @deorder[@reorder] = 0 .. $#reorder; print " keyword = $keyword\n\nplaintext = $plaintext\n\n"; my $encoded = encode( $plaintext, \%char2pair, \@reorder ); print " encoded = $encoded\n\n"; my $decoded = decode( $encoded, \%pair2char, \@deorder ); print " decoded = $decoded\n"; sub encode { my ($plain, $c2p, $order) = @_; my $len = @$order; join ' ', (transpose( $plain =~ s/./$c2p->{$&}/gr =~ /.{1,$len}/g ))[@$order]; } sub decode { my ($encoded, $p2c, $order) = @_; (join '', transpose((split ' ', $encoded)[@$order])) =~ s/../$p2c->{$&}/gr; } sub transpose { map join('', map {s/.// ? $& : ''} @_), 1 .. length $_[0] }