#!/usr/bin/perl -w
################################################################
# phibar.pl : Sinkov's Phi Test for a text                     #
#--------------------------------------------------------------#
# Detect the most likely value for the period of a periodic    #
#   polyalphabetic ciphertext.                                 #
#                                                              #
# Inputtext from STDIN                                         #
# Command line parameter: limit $maxp for periods to be        #
#   tested.                                                    #
# Output: a list of pairs (ltest, phibar) where                #
#   ltest is the period under test,                            #
#   phibar is the corresponding Sinkov phi-value.              #
#--------------------------------------------------------------#
# Transliteration of special characters according to English   #
#   rules                                                      #
# For special characters of other languages use preptext.pl    #
#   first.                                                     #
#--------------------------------------------------------------#
# Klaus Pommerening 2014-Jan-04                                #
#                                                              #
# This program is freeware. Use it as you like.                #
# Usual disclaimers apply.                                     #
################################################################

require "auxcrypt.pl";  # Use standard alphabet
                           #   as global variables $alphabet,
                           #   @alphabet, and %sa.
                           # Use procedures
                           #   &gettext, &phi.
$maxp = $ARGV[0];          # Get desired maximal period from command line.
if ($maxp < 2) {die("Nothing to do!");}
$testtext = &gettext;      # Read (cipher) text from standard input.
$rr = length($testtext);   # Get its length.
@textlist = split(//,$testtext); # Split into single letters.

for ($l = 1; $l <= $maxp; $l++) { # Test $l for period
  @parttext = ();                 # Initialize list @parttext
  @phivalues = ();                # Initialize list of @phivalues

# ---------- Pick $l partial texts
  for ($i = 0; $i < $rr; $i++) {         # Loop through @textlist
    $parttext[$i % $l] .= $textlist[$i]; # and append the $i-th letter
                                         # to parttext[$i mod $l].
    } #--- for $i --------------------------------------

  for ($j = 0; $j < $l; $j++) {           # For each of the $l parttexts
    $phivalues[$j] = &phi($parttext[$j]); # calculate the phi value.
    } #--- for $j --------------------------------------

  $mean = 0;                    # Initialize mean value.
  for ($j = 0; $j < $l; $j++) { # Sum the $l
    $mean += $phivalues[$j];    # single phi values.
    }
  $mean = $mean/$l;              # Calculate mean value of @phivalues.

  print "Period under test: ", $l, " | Sinkov phi value: ", $mean, "\n";
  } #--- for $l ----------------------------------------
