use strict; use warnings; use List::Util qw( max sum ); my @stats = qw( hp mana spells ); my %rates = ( hp => 12, mana => 17, spells => 7 ); my %stats = ( hp => 60, mana => 80, spells => 31 ); my %needed = ( hp => 51, mana => 107, spells => 38 ); { my $avail = sum @stats{@stats}; our @parts; ('.' x $avail) =~ / ^ (.*) (?(?{ length($1) > $needed{$stats[0]} })(?!)) (.*) (?(?{ length($2) > $needed{$stats[1]} })(?!)) (.*) (?(?{ length($3) > $needed{$stats[2]} })(?!)) \z (??{ push @parts, { $stats[0] => length($1), $stats[1] => length($2), $stats[2] => length($3), }; }) (?!) /x; my ($result) = sort { $a->[1] <=> $b->[1] } map { my $part = $_; my $time = max map { ( $needed{$_} - $part->{$_} ) / $rates{$_} } @stats; [ $_, $time ] } @parts; print(join("\t", @stats, 'hours'), "\n"); printf(join("\t", ("%d")x@stats, "%.2f") . "\n", @{$result->[0]}{@stats}, $result->[1], ); } #### hp mana spells hours 43 95 33 0.71