#! /n/gnu/bin/gawk -f
# Last edited on 1998-07-12 05:00:44 by stolfi

BEGIN {
  usage = ( "compute-cond-tuple-info \\\n" \
            "  -v order=ORDER \\\n" \
            "  -v place=PLACE \\\n" \
            "  -v alphabetSize=NUM \\\n" \
            "  < COUNTFILE > INFOTBL" \
          );

  # The file COUNTFILE must have entries COUNT WORD where COUNTS
  # is a positive occurrence count for the string WORD in some text.
  # The length of all WORDs must be ORDER.
  #
  # Computes the conditional information content for the PLACEth
  # character of each WORD in COUNTFILE, assuming the rest of WORD is
  # known.  Outputs entries INFO WORD for each input WORD.
  #
  # The "alphabetSize" value is used in probability estimation.
  # The input should not have more than that number of distinct 
  # letters in the PLACEth position.

  abort = -1;
  if (order == "") { error("should define \"order\""); } 
  if ((order < 1) || (order > 20)) { error("funny \"order\""); } 
  if (place == "") { error("should define \"place\""); } 
  if ((place < 1) || (place > order)) { error("funny \"place\""); } 
  if (alphabetSize == "") { error("should define \"alphabetSize\""); } 
  if ((alphabetSize < 1) || (alphabetSize > 168)) { error("funny \"alphabetSize\""); } 

  split("", full_count);
  split("", part_count);
  split("", letter_count);
  n_letters = 0;
  tuple_count = 0;
  n_tuples = 0;
}

// {
  if (abort >= 0) { exit(abort); }
  if (NF != 2) { error(("line " NR ": format error")); }
  c = $1;
  w = $2;
  if (length(w) != order) { error(("line " NR ": wrong word length")); }
  full_count[w] += c;
  p = (substr(w,1,place-1) substr(w,place+1,order-place));
  part_count[p] += c;
  a = substr(w,place,1);
  if(! (a in letter_count)) { n_letters ++; }
  letter_count[a] += c;
  tuple_count += c;
  n_tuples ++;
}

END {
  if (abort >= 0) { exit(abort); }
  if (n_letters > alphabetSize) 
    { error(("true alphabet size = " n_letters)); }
  scale = -1/log(2.0);
  for(w in full_count) 
    { p = (substr(w,1,place-1) substr(w,place+1,order-place));
      a = substr(w,place,1);
      cf = full_count[w]; cp = part_count[p];
      # Assumes that, "a priori", all letters are equally likely:
      fr = (cf + 1)/(cp + alphabetSize);
      printf "%7.3f %s\n", scale*log(fr), w;
    }
}

function error(msg)
{ printf "%s\n", msg >>  "/dev/stderr";
  abort = 1; exit 0;
}