#! /usr/bin/perl
#
#
# Perform a Wilcoxon two sample Test on ARGV[0] vs ARGV[1]
# or on two columns in ARGV[0] ("\n" separated)
# Calculates W. 
# 
# If ARGV[0] is a filename (or '-')
# the corresponding file is read (or STDIN).
#
# E.g., 
# > echo -e '1 2\n2 3\n3 4\n4 3\n'| WilcoxonW.pl -
# => 17
#
#
# Copyright (C) 1996, 2001  Rob van Son
# 
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
# 
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
# 
#
# Get input 
#
# Get STDIN if needed
if($ARGV[0] eq '-')
{
	$ARGV[0] = join("\n", <STDIN>);
}
elsif(-e $ARGV[0])
{
	open(INPUT, "<$ARGV[0]") || die "<$ARGV[0]: $!";
	$ARGV[0] = join("\n", <INPUT>);
};

# The second argument contains alphanumeric characters (i.e., exists)
if($ARGV[1] =~ /[\w]+/)
{ @A = sort {$a <=> $b} split(' ', $ARGV[0]);
  @B = sort {$a <=> $b} split(' ', $ARGV[1]);
}
else	# Use a double column from the first entry. Note that the FIRST column
{ @AB = split('\n', $ARGV[0]);	# must be the longer one OR null entries must be
  foreach (@AB)			# entered with a '-' character
  { @temp = split(' ');
    if($temp[0] =~ /\w/){ push(@Aunsorted, $temp[0]);};
    if($temp[1] =~ /\w/){ push(@Bunsorted, $temp[1]);};
  };
  @A = sort {$a <=> $b} @Aunsorted;
  @B = sort {$a <=> $b} @Bunsorted;
};
#
@TotalList = sort {$a <=> $b} (@A, @B);
#
# Replace values by ranks
$previous = undef;
$start = 0;
for($i=0; $i <= $#TotalList; ++$i)
{ if($TotalList[$i] == $previous)
  { $mean_rank = ($start+$i+2)/2.0;
    for($j=$start; $j<=$i; ++$j)
    { $Total_rank[$j] = $mean_rank;
    };
  }
  else
  { $Total_rank[$i] = $i+1;
    $previous = $TotalList[$i];
    $start = $i;
  };
};
#
# Determine the shortest list
@shortest = ($#A < $#B) ? @A : @B;
$nShortest = $#shortest+1;
# Summ the ranks in the shortest list
$W = 0;
foreach $Value (@shortest)
{
  $i = 0;
  until($i > $#TotalList || $Value == $TotalList[$i]){ ++$i;};
  $W += $Total_rank[$i];
};
#
# Output W
printf("%10d", $W);
