use strict; use warnings; use List::Util qw[ reduce ]; my $num; # Used in sub, but could be passed if you wanted sub closest { # Args are target and factor-list my ($target, @factors) = @_; # Take the biggest factor my $top_factor = pop @factors; # Find multiple of that factor closest to (and above) target my $guess = int($target) - $target % $top_factor + $top_factor; # Oscillate around the target, looking at multiples of top_factor # until you get one that divides the product for (my $i=$top_factor; $num % $guess; $i += $top_factor) { $guess += ( $target <=> $guess ) * $i; } # Check the complementary factor my $complement = $num / $guess; abs($target - $complement) < abs($target - $guess) ? $complement : $guess ; } my @pfs = (2,2,2,3,3,3,5,5,5,17,19,19,19,19); # Compute product of factors our ($a, $b); $num = reduce { $a * $b } @pfs; my $root = sqrt $num; print "N=$num, R=$root\n"; print closest($root, 1, @pfs), "\n";