#!/usr/bin/perl -w

sub parse_matr {
  my $fn=shift;
  my $l;my @l;my $k2;

  open FM,"<$fn" or return;

  $l=<FM>;
  my @k1=split ' ',$l;
  $i=0;

  while ($l=<FM>) {
    @l=split ' ',$l;
    $k2=shift @l;
    for ($j=0;$j<=$#k1;$j++) {
      $matr{$k2}->{$k1[$j]}=shift @l;
    }
  }
  close FM;
}

sub compact {
  my @r;

  @_=sort @_;
  push @r,shift @_;
  while (@_) {
    if ($_[0] eq $r[-1]) { shift;next }
    push @r,shift @_;
  }
  return @r;
}

sub save_matr {
  my $fn=shift;
  my $l;
  my @k1;my @k2;

  open FM,">$fn";

  @k2=sort keys %matr;
  @k1=();for (@k2) {@k1=(@k1,keys %{$matr{$_}})};
  @k1=compact(@k1);

  print FM "  @k1\n";

  for ($i=0;$i<=$#k2;$i++) {
    print FM "$k2[$i]";
    for ($j=0;$j<=$#k1;$j++) {
      print FM " ",defined($matr{$k2[$i]}->{$k1[$j]})?$matr{$k2[$i]}->{$k1[$j]}:0;
    }
    print FM "\n";
  }
  close FM;
}

%folds=(
	'~' => '`',
	'!' => '1',
	'@' => '2',
	'#' => '3',
	'$' => '4',
	'%' => '5',
	'^' => '6',
	'&' => '7',
	'*' => '8',
	'(' => '9',
	')' => '0',
	'{' => '[',
	'}' => ']',
	'"' => '\'',
	'<' => ',',
	'>' => '.',
	'P' => 'p',
	'Y' => 'y',
	'F' => 'f',
	'G' => 'g',
	'C' => 'c',
	'R' => 'r',
	'L' => 'l',
	'?' => '/',
	'+' => '=',
	'|' => '\\',
	'A' => 'a',
	'O' => 'o',
	'E' => 'e',
	'U' => 'u',
	'I' => 'i',
	'D' => 'd',
	'H' => 'h',
	'T' => 't',
	'N' => 'n',
	'S' => 's',
	'_' => '-',
	':' => ';',
	'Q' => 'q',
	'J' => 'j',
	'K' => 'k',
	'X' => 'x',
	'B' => 'b',
	'M' => 'm',
	'W' => 'w',
	'V' => 'v',
	'Z' => 'z',
);

for (values %folds) {
  push @folds,$_;push @folds,$_;
}
%folds=(%folds,@folds);

sub fold_char {
  if (exists $folds{$_[0]}) {
    return $folds{$_[0]};
  } else {
    return undef;
  }
}

sub upd_matr {
  my $fn=shift;
  my $l;

  open FM,"<$fn";

  while ($l=<FM>) {
    for ($i=0;$i<length($l)-1;$i++) {
      $j=fold_char(substr($l,$i,1));
      $k=fold_char(substr($l,$i+1,1));
      if (defined($j) && defined($k)) {
	$matr{$j}->{$k}++;
      }
    }
  }
  close FM;
}

$MATRFN='/tmp/freq.matr';

parse_matr($MATRFN);

while ($f=shift) {
  upd_matr($f);
}

save_matr($MATRFN);
