logo       
Google Custom Search
    AddThis Social Bookmark Button
-->

[SPOILER] Perl Quiz-of-the-Week #12: msg#00082

Subject: [SPOILER] Perl Quiz-of-the-Week #12
I chose to waste time and store the whole bar chart in array of arrays of
chars.I
chose to scale vertically only if the height was to small for the data.
I also added horizatonal centering and padding between bars. I did no
scaling
horizontally so if your width is too small then you lose the data on the
right.
Unfortunantely since I stored all the values individually I had to loop
again to concatenate them. Sorry no comments. I did enjoy having a variable
char for the background characters instead of spaces. I liked to use a '~'
for my debugging.

--------------------------------------

#!/usr/bin/perl

use strict;
use warnings;

my $HISTOGRAM_WIDTH = 18;
my $HISTOGRAM_HEIGHT = 16;
my $HISTOGRAM_CHAR;

my @hist = histogram(11, 2, 31, 24, 7);

print @hist;

sub histogram {

  my @data = @_;

  $HISTOGRAM_WIDTH  ||= 15;
  $HISTOGRAM_HEIGHT ||= 15;
  $HISTOGRAM_CHAR   ||= '*';

  my $HISTOGRAM_NONCHAR = ' ';

  my $MARGIN;
  my $PADDING;

  if ($HISTOGRAM_WIDTH <= @data) {
    $MARGIN = 0;
    $PADDING = 0;
  } elsif ($HISTOGRAM_WIDTH < 2 * @data) {
    $MARGIN = int(($HISTOGRAM_WIDTH % @data) / 2);
    $PADDING = 0;
  } elsif ($HISTOGRAM_WIDTH >= 2 * @data) {
    $PADDING = int(($HISTOGRAM_WIDTH / @data))-1;
    $MARGIN = int(($HISTOGRAM_WIDTH % @data) / 2)+1;
  }

  my $max_value = 0;
  for (@data) {$max_value = $_ if ($_ > $max_value)}

  if ($max_value > $HISTOGRAM_HEIGHT) {
    for (@data) {$_ = sprintf("%d", $_*$HISTOGRAM_HEIGHT/$max_value)}
  }

  my $chart_ref = [];

  my ($i, $j) = (0, 0);
  my @tmp = @data;
  while ($j < $HISTOGRAM_HEIGHT) {

    if ($i < $MARGIN) {
      $chart_ref->[$i][$j] = $HISTOGRAM_NONCHAR;
      $i++;
      next;
    }


    my $val = shift @tmp;
    $chart_ref->[$i][$j] = (defined $val && $val > $j)
                     ? $HISTOGRAM_CHAR : $HISTOGRAM_NONCHAR;

    for (my $p = 0; $p < $PADDING; $p++) {
      $i++;
      $chart_ref->[$i][$j] = $HISTOGRAM_NONCHAR;
    }

    next if (++$i < $HISTOGRAM_WIDTH);
    $i = 0;
    $j++;
    @tmp = @data;
  }

  ($i, $j) = (0, 0);

  my @retval;

  while ($j < $HISTOGRAM_HEIGHT) {

    $retval[$j] .= $chart_ref->[$i][$HISTOGRAM_HEIGHT-$j-1];

    next if (++$i < $HISTOGRAM_WIDTH);
    $retval[$j] .= "\n";
    $i = 0;
    $j++;

  }

  return @retval;

}

_________________________________
Dave Kershaw
Database Developer, e-Business Data & Information
VWR International, http://www.vwr.com
Phone: 610-429-5558





<Prev in Thread] Current Thread [Next in Thread>