in reply to alternatives to if and series of elsif

This does the same thing as your compare

use POSIX 'ceil'; use List::Util qw( min max ); my $Base = 15; my $Max = 24; my $Incr = 2000; sub compare { my ( $points, $quota ) = @_; my $new = max( min( $Max, ( ceil( $points/$Incr ) - 1 ) + $Base ), $ +Base ); return $new > $quota ? $new : $Base; }

Update: Fixed bug in response to kiat's comment. (In my original version, the min was applied, incorrectly, at the test in the return statement not in the earlier assignment. This produced results that differed from those of kiat's original compare for $points > 2000.) Also, my original tested only for non-zero $points whereas it should have tested for positive $points. But this amounts to including a max in the definition of $new, which simplifies the last test further. I fixed that too.

the lowliest monk

Replies are listed 'Best First'.
Re^2: alternatives to if and series of elsif
by kiat (Vicar) on Jul 03, 2005 at 11:59 UTC
    Interesting.
    return ( $points && min( $Max, $new ) > $quota ) ? $new : $Base;
    Your code (assuming $points is true) reduces the conditional test to a test on the min of the $Max or $new against $quota. I'm trying to understand why it's sufficient without also testing for points against some default value:
    if ($points > 18000 && $quota < 24) { return 24; }

      Because my original version of the algorithm was wrong, that's why! :) I've fixed it. I don't know if it is any clearer. The basic idea is that the tests for points and quota are not independent; they follow the form:

      $points > 2000*X && $quota < 15+X
      for some integer 0 < X < 10. One can eliminate the redundancy between these two tests. Algebraically, the above is equivalent to
      $points/2000 > X && X > $quota-15
      ...which can be further reduced to
      $points/2000 + 15 > $quota
      ...except that there are edge cases (basically, X must be an integer strictly between 0 and 10) which make the algorithm a bit more complex.

      the lowliest monk

        Great thanks, tlm!

        Now I understand how you got rid of $points > 2000. I was wondering how $new > $quota took care of everything.

        I ran gsiems's against your original version and it says "looks ok". Then then I tried to understand how your code works and that got me wondering about $new > $quota being a sufficient test.

        Cheers and thanks once again :)