RosettaCodeData/Task/Text-processing-1/Perl/text-processing-1-2.pl

116 lines
2.6 KiB
Perl

use strict;
use warnings;
use constant RESULT_TEMPLATE => "%-19s = %12.3f / %-6u = %.3f\n";
my $parser = Parser->new;
# parse lines and print results
printf RESULT_TEMPLATE, $parser->parse(split)
while <>;
$parser->finish;
# print total and summary
printf "\n".RESULT_TEMPLATE."\n", $parser->result;
printf "the maximum of %u consecutive bad values was reached %u time(s)\n",
$parser->bad_max, scalar $parser->bad_ranges;
# print bad ranges
print for map { ' '.join(' - ', @$_)."\n" } $parser->bad_ranges;
BEGIN {
package main::Parser;
sub new {
my $obj = {
SUM => 0,
COUNT => 0,
CURRENT_DATE => undef,
BAD_DATE => undef,
BAD_RANGES => [],
BAD_MAX => 0,
BAD_COUNT => 0
};
return bless $obj;
}
sub _average {
my ($sum, $count) = @_;
return ($sum, $count, $count && $sum / $count);
}
sub _push_bad_range_if_necessary {
my ($parser) = @_;
my ($count, $max) = @$parser{qw(BAD_COUNT BAD_MAX)};
return if $count < $max;
if ($count > $max) {
$parser->{BAD_RANGES} = [];
$parser->{BAD_MAX} = $count;
}
push @{$parser->{BAD_RANGES}}, [ @$parser{qw(BAD_DATE CURRENT_DATE)} ];
}
sub _check {
my ($parser, $flag) = @_;
if ($flag <= 0) {
++$parser->{BAD_COUNT};
$parser->{BAD_DATE} = $parser->{CURRENT_DATE}
unless defined $parser->{BAD_DATE};
return 0;
}
else {
$parser->_push_bad_range_if_necessary;
$parser->{BAD_COUNT} = 0;
$parser->{BAD_DATE} = undef;
return 1;
}
}
sub bad_max {
my ($parser) = @_;
return $parser->{BAD_MAX}
}
sub bad_ranges {
my ($parser) = @_;
return @{$parser->{BAD_RANGES}}
}
sub parse {
my $parser = shift;
my $date = shift;
$parser->{CURRENT_DATE} = $date;
my $sum = 0;
my $count = 0;
while (my ($value, $flag) = splice @_, 0, 2) {
next unless $parser->_check($flag);
$sum += $value;
++$count;
}
$parser->{SUM} += $sum;
$parser->{COUNT} += $count;
return ("average($date)", _average($sum, $count));
}
sub result {
my ($parser) = @_;
return ('total-average', _average(@$parser{qw(SUM COUNT)}));
}
sub finish {
my ($parser) = @_;
$parser->_push_bad_range_if_necessary
}
}