Разве это не просто:
y = (x-min)/(max-min)*9+1
Возможно с некоторым округлением, используя
sprintf '%.0f'
use strict;
use warnings;
use List::MoreUtils qw( minmax );
my %people = (
John => { height => 72.3, weight => 212, age => 662256000 },
Peter => { height => 64.5, weight => 232, age => 1292976000 },
Frank => { height => 78.5, weight => 140, age => 977616000 },
Susan => { height => 65.8, weight => 355, age => 1229904000 },
Judy => { height => 69.0, weight => 105, age => 599184000 },
Mary => { height => 72.7, weight => 76, age => 283824000 },
);
sub scale {
my ($min, $max, $x) = @_;
return ($x-$min)/($max-$min)*9+1;
}
my ($min_height, $max_height) = minmax( map $_->{height}, values %people );
my ($min_weight, $max_weight) = minmax( map $_->{weight}, values %people );
my ($min_age, $max_age ) = minmax( map $_->{age }, values %people );
for my $name (keys %people) {
my $person = $people{$name};
printf("%-6s height: %2.0f/10 weight: %2.0f/10 age: %2.0f/10\n",
"$name:",
scale($min_height, $max_height, $person->{height}),
scale($min_weight, $max_weight, $person->{weight}),
scale($min_age, $max_age, $person->{age }),
);
}
Выход:
Susan: height: 2/10 weight: 10/10 age: 9/10
John: height: 6/10 weight: 5/10 age: 4/10
Mary: height: 6/10 weight: 1/10 age: 1/10
Judy: height: 4/10 weight: 2/10 age: 4/10
Peter: height: 1/10 weight: 6/10 age: 10/10
Frank: height: 10/10 weight: 3/10 age: 7/10