Beefy Boxes and Bandwidth Generously Provided by pair Networks
Welcome to the Monastery
 
PerlMonks  

Re: OT: Finding Factor Closest To Square Root

by Roy Johnson (Monsignor)
on Feb 22, 2005 at 14:53 UTC ( [id://433350]=note: print w/replies, xml ) Need Help??


in reply to OT: Finding Factor Closest To Square Root

Here it is, fast and accurate. The comments should describe the algorithm pretty well.
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";

Caution: Contents may have been coded under pressure.

Replies are listed 'Best First'.
Re^2: OT: Finding Factor Closest To Square Root
by Limbic~Region (Chancellor) on Feb 27, 2005 at 21:16 UTC
    Roy Johnson,
    Here it is, fast and accurate.

    Well it is certainly fast, but unfortunately it is not always accurate. Try (3, 5, 16381, 77951) - it should produce 81905 but it produces 77951. I didn't bother debugging as I was gathering statistics.

    Cheers - L~R

      You're right. I had an erroneous understanding: that the closest factor that included top_factor would be paired with the closest factor that didn't. Instead, it's paired with the closest factor on the other side of root that doesn't include top_factor. So you have to check both sides of root. Here's a fixed version:
      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 my $i; for ($i = $top_factor; $num % $guess; $i += $top_factor) { $guess += ( $target <=> $guess ) * $i; } # Check the complementary factor my $complement = $num / $guess; # Look for a multiple of $top_factor between the last guess on the # other side of sqrt and $complement my $direction = ($target <=> $guess); my $new_guess = $guess + $direction * $i; while (($complement <=> $new_guess) == $direction and $num % $new_ +guess) { $new_guess += $top_factor * $direction; } if ($new_guess and $num % $new_guess == 0 and (($complement <=> $new_guess) == $direction)) { $guess = $new_guess; $complement = $num/ $guess; } abs($target - $complement) < abs($target - $guess) ? $complement : $guess ; } my @pfs = (3, 5, 16381, 77951); # 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";

      Caution: Contents may have been coded under pressure.
        Roy Johnson,
        What am I missing - it still produces 77951 as the answer?

        Cheers - L~R

Re^2: OT: Finding Factor Closest To Square Root
by QM (Parson) on Feb 23, 2005 at 13:15 UTC
    That's sweet. I especially like the use of <=> in
    $guess += ( $target <=> $guess ) * $i;
    to choose which direction to move.

    -QM
    --
    Quantum Mechanics: The dreams stuff is made of

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://433350]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others wandering the Monastery: (8)
As of 2024-04-23 13:14 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found