use warnings; use strict; use Data::Dumper; my %value = ( A => 2.74, B => 2.64, C => 2.5, ); my %factor = ( A => 50/100, B => 55/100, C => 60/100, ); sub calc { # fetch arguments my $expression = shift; my $values = shift; my $factors = shift; # build an array of normalized terms # (normalize = replace non existant factors by 1) # as in 4ABC => 4A 1B 1C my @term; while ( $expression =~ /([0-9]*)([A-Z])/g ) { push @term, [$1?$1:1, $2]; } # now iterate over that array and do the # calculation my $result = 1; $result *= $_->[0] * $values->{$_->[1]} * $factors->{$_->[1]} for @term; return $result; } print calc ("4ABC", \%value, \%factor), "\n"; print calc ("2A2B2C", \%value, \%factor), "\n"; print calc ("3C", \%value, \%factor), "\n"; print calc ("ABC", \%value, \%factor), "\n";