#!/usr/bin/perl -w
use strict;

# SUMMARY NOTES
# -------------
# => stretches height to $max
# => stretches width to scalar @_
# => scales output by integer multiples if possible

use vars qw( $HISTOGRAM_WIDTH $HISTOGRAM_HEIGHT $HISTOGRAM_CHAR );
$HISTOGRAM_WIDTH = 20;
$HISTOGRAM_HEIGHT = 20;
$HISTOGRAM_CHAR = 'H';

sub histogram{
  my @list = @_;
  my @response  = ();
  my $x_scale   = 1;   # horizontal scaling factor
  my $y_scale   = 1;   # vertical scaling factor
  my $max_value = 0;   # greatest value (tallest bar) in @list

  $HISTOGRAM_WIDTH  ||= 0;
  $HISTOGRAM_HEIGHT ||= 0;
  $HISTOGRAM_CHAR   ||= 'H';
  $HISTOGRAM_CHAR   = unpack('a1',$HISTOGRAM_CHAR); # must be 1 char long.

# determine y scaling factor. Increase $HISTOGRAM_HEIGHT
# if what we got is too big to fit.
  foreach( @list ){
	if( $_ > $max_value ){
	  $max_value = $_;
	}
  }
  if($max_value > $HISTOGRAM_HEIGHT){
	$HISTOGRAM_HEIGHT = $max_value;
  }
  $y_scale = int($HISTOGRAM_HEIGHT / $max_value);

# determine x scaling factor. Increase $HISTOGRAM_WIDTH
# if we got too many values to fit. Can't just omit some...
  if( $HISTOGRAM_WIDTH < $#list ){
	$HISTOGRAM_WIDTH = $#list;
  }
  $x_scale = int($HISTOGRAM_WIDTH / $#list);

# build @response, based on @list and scaling factors.
# iterate over @list $HISTOGRAM_HEIGHT times.
# for each element in @list, if ($_ * scaling factor) is >
# current position in the histogram (one less than the y-value of the graph),
# then append $x_scale number of $HISTOGRAM_CHAR to the current element
# of @response. Otherwise, append $x_scale number of spaces.

  for( my $i=0; $i<$HISTOGRAM_HEIGHT; $i++ ){
	foreach(@list){
	  if( $_ * $y_scale > $i ){
		$response[$i] .= $HISTOGRAM_CHAR x $x_scale;
	  }
	  else{
		$response[$i] .= ' ' x $x_scale;
	  }
	}
	$response[$i] .= "\n";
  }
  return reverse @response;
}
__END__
