# $Id: john_j_trammell.pl,v 1.1 2004/09/15 20:30:41 trammell Exp $
# vim: set ai expandtab ts=4 :

package main;

use vars qw/ $HISTOGRAM_DEBUG $HISTOGRAM_WIDTH
    $HISTOGRAM_HEIGHT $HISTOGRAM_CHAR /;

sub histogram {
    my @data = @_; 
    my $max    = max_entry(@data);

# decide histogram dimensions

    my $width  = int($HISTOGRAM_WIDTH)  || scalar(@data);
    my $height = int($HISTOGRAM_HEIGHT) || $max;
    my $char   = $HISTOGRAM_CHAR        || '*';

    die "Bad histogram width: '$width'" if $width < 1;
    die "Bad histogram height: '$height'" if $height < 1;
    die "Bad histogram character: '$char'" if $char =~ /../;

    if ($HISTOGRAM_DEBUG) {
        warn <<EOF;
\$width  = $width
\$height = $height
\$char   = $char
\$max    = $max
EOF
    }

# "raster" over "pixels" (0,0) => ($width-1, $height-1)

    my @p;
    for my $v (0 .. $height-1) {
        for my $u (0 .. $width-1) {
            my $x = sprintf "%.0f", $u * scalar(@data) / $width;
            my $y = sprintf "%.0f", ($v+1) * $max / $height;
            $p[$v][$u] = lookup(\@data, $x, $y) ? $char : ' ' ;
        }
    }

# reformat pixels into output lines

    return reverse map { join '', @{$p[$_]}, "\n" } 0 .. $height-1;
}

sub max_entry {
    my ($max, @x) = @_;
    for (@x) { $max = $_ if $_ > $max }
    return $max;
}

sub lookup {
    my ($data, $x, $y) = @_;
    return $data->[$x] >= $y ? 1 : 0 ;
}

1;

__END__

command-line usage:

  perl -e 'require "histogram.pl"; print histogram(@ARGV)' 4 3 7 6


