#!/usr/bin/perl -w
################################################################
# adjust.pl                                                    #
#   Test version                                               #
#--------------------------------------------------------------#
# Find the alphabet shift that optimizes the chi value of two  #
#   texts.                                                     #
#   ( = KULLBACK's cross-product sum)                          #
#--------------------------------------------------------------#
# Input from command line: filename of primary alphabet        #
# Input from command line: filenames of two texts              #
#   The input texts are assumed to have only letters in A..Z.  #
# Output to STDOUT : the optimal shift value.                  #
#--------------------------------------------------------------#
# Klaus Pommerening 2014-Jan-05, 2014-Jun-11                   #
#                                                              #
# This program is freeware. Use it as you like.                #
# Usual disclaimers apply.                                     #
################################################################

require "auxcrypt.pl";  # Use procedures &to26eng, &kappa.

### Primary Alphabet ##############
open(FILE0,$ARGV[0]);             # Use first filename from command line
                                  #   for primary alphabet
chomp(@inlist0 = <FILE0>);        # Read input line by line,
                                  #   chop trailing CR.
foreach $line (@inlist0) {        # Change each line
  $line = &to26eng($line); }      #   to Alphabet [A..Z].
$alphtext = join("",@inlist0);    # Join lines as 1 string.
close(FILE0);
$primalph = &makeperm($alphtext); # Generate the primary alphabet as string
@primalph = split(//,$primalph);  # and as list of characters
for ($i = 0; $i < @primalph; $i++) { # Indices for alphabet
  $pa{$primalph[$i]} = $i;           #   as hash %pa
  }
### End (Primary Alphabet) ########

### Get the Two Texts #############
open(FILE1,$ARGV[1]);             # Use first filename from command line
chomp(@inlist1 = <FILE1>);        # Read input line by line,
                                  #   chop trailing CR.
foreach $line (@inlist1) {        # Change each line
  $line = &to26eng($line); }      #   to Alphabet [A..Z].
$text1 = join("",@inlist1);       # Join lines as 1 string.
close(FILE1);
open(FILE2,$ARGV[2]);             # Use first filename from command line
chomp(@inlist2 = <FILE2>);        # Read input line by line,
                                  #   chop trailing CR.
foreach $line (@inlist2) {        # Change each line
  $line = &to26eng($line); }      #   to Alphabet [A..Z].
$text2 = join("",@inlist2);       # Join lines as 1 string.
close(FILE2);
### End (Two Texts ################

print "Optimal shift: ", &optshift($text1,$text2), "\n";

################################################################
# Subroutine optshift                                          #
#   Input: two strings $_[0] and $_[1] in A..Z                 #
#   Output: the alphabet shift of $_[1] that maximizes the chi #
#     (cross-product sum) of $_[0] and shifted($_[1]).         #
# Byproduct: The routine prints a list of all chi values.      #
################################################################
sub optshift {
  # Initialize locl variables.
  my $txt0 = $_[0];
  my $txt1 = $_[1];
  my @chilist = ();
  my $chivalue;
  my $i;
  my $shift = 0;

  # Get list of chi values for each shift. ------------------
  while ($shift < 26) {            # Loop over $shift.
    print $txt1, "----- Shift: ", $shift, " ----- ";
    $chivalue = &chi($txt0,$txt1); # Cross-product sum
    print "Chi = ", $chivalue, "\n";
    push @chilist, $chivalue;
    $shift++;
    $txt1 = &primsh($txt1,1);      # 
    } #--- while -----

  # Pick maximum value. --------------------------------------
  my $max = 0;
  my $idx = 0;
  for ($i = 0; $i < 26; $i++) {
    if ($chilist[$i] > $max) {
      $max = $chilist[$i];
      $idx = $i;
      } #--- if -----
    } #--- for $i -----
  return $idx;
  }

################################################################
# Subroutine primsh                                            #
#   Input: a textstring $_[0]                                  #
#          a shift value $_[1]                                 #
#   Output: the textstring that has each letter shifted in the #
#           primary alphabet (golbal variable $primalph)       #
################################################################
sub primsh {
  my $mytext = $_[0];
  my $sh = $_[1];
  my $len = length($mytext);
  my @textlist = split(//,$mytext);
  my $j = 0;
  my $index = 0;
  my $newindex = 0;
  my $letter;
  my @newlist = ();

  for ($j = 0; $j < $len; $j++) {   # Loop over the input text
    $index = $pa{$textlist[$j]};
    $newindex = ($index + $sh) % 26;
    $letter = $primalph[$newindex]; # shifted letter
    $newlist[$j] = $letter;
    }
  return join("",@newlist);
  }
