#!/usr/local/bin/perl
###
### This perl script simulates a noisy channel model: it reads
### characters and writes them but it deliberately makes errors
### when processing vowels.
###
### Almost every line of code in the program has some extra comment
### explaining what it does. Comments for the important parts in
### the script have been marked with three # signs instead of 
### one. You may ignore the rest of the program
###
### usage: ./messUp < file
#
# 961116 erik.tjong@ling.uu.se
# 961125 adapted pairs
# 971015 added extra code and extra variables
# 971022 modified subroutine printOneOf

# initialize the random function with a random value (Perl book p188)
#
srand(time|$$);

# read all lines from the input file and process the line
#
while (<>) {

   # $_ is the current item that is being processed; here it is a line
   #
   $line = $_;
   
   # divide the line in characters and put them in the list @chars
   # the split function is explained in the Perl book on page 185
   #
   @chars=split(//,$line);
   
   # process the characters on the line
   #
   foreach (@chars) {

      # $_ is the current item that is being processed; here it is a word
      #
      $character = $_;

      ### (assignments 2.1 and 2.5)
      ###
      ### if the current character is one of some special set of
      ### characters then replace the character with some other
      ### character or keep it (like in the sixth bit flip model)
      ### "eq" means "is equal to"
      ###
         if ($character eq 'e') { &printOneOf(2,'e','ä'); }
      elsif ($character eq 'ä') { &printOneOf(2,'e','ä'); }
      elsif ($character eq 'a') { &printOneOf(2,'a','u'); }
      elsif ($character eq 'u') { &printOneOf(2,'a','u'); }
      elsif ($character eq 'i') { &printOneOf(2,'i','y'); }
      elsif ($character eq 'y') { &printOneOf(2,'i','y'); }
      elsif ($character eq 'o') { &printOneOf(2,'o','å'); }
      elsif ($character eq 'å') { &printOneOf(2,'o','å'); }

      ### (assignments 2.1 and 2.5)
      ###
      ### if the character was not in [eaioäuåy] then do not change it
      ###
      else { printf '%s',$character; }
   }
}

# printOneOf is a subroutine which should be called as &printOneOf(N,A,B...) 
# it will print one of the characters A, B... at random with a probability
# of 1/N 
#
sub printOneOf {

   # get the number of elements 
   #
   local($count) = @_;

   # we have extracted the first element of the argument list so move
   # it away
   # 
   shift(@_);

   # store the characters that can be changed in the list @chars
   #
   local(@chars) = @_;
   
   # we need a random value between 0 and 1: 
   # the function rand gives us one
   #
   $randomValue = rand;

   # check all intervals from 0 to 1 and print the character that
   # belongs to a certain interval based on $randomValue 
   #
   # start with interval 1
   #
   local($i) = 1;
   #
   # initialize the boolean flag $printed at 0 (=false)
   #
   local($printed) = 0;
   #
   # keep on checking intervals as long as there not all have been
   # checked and nothing has been printed
   #
   while (($i<=$count)&&(! $printed)) {

      # check if $randomValue lies in the interval
      # 
      if ($randomValue <= ($i/$count)) { 

         # if it lies in the interval then print the correct character
         #
         printf @chars[($i-1)];
         #
         # set the boolean flag $printed at 1 (=true)
         #
         $printed = 1;
      } 
      #
      # select next interval
      #
      $i++;
   }
   # do something reasonable if no character got printed: print the
   # first alternative
   #
   if (! $printed) { printf @chars[0]; }
}
