I got to wondering if these alternatives were functionally the same as the original... So I rigged up the following test (I think it's a valid enough test). To the extent that I transcribed the various functions correctly and that my testing is valid you may want to be careful which method you implement.
#!/usr/bin/perl -w use strict; my %test_data; my %test_result; my $test_size = 25; # Generate some random test data, run it through the # original compare sub, print and store the result: print "Test data:\n"; print "pts qt result\n"; print "----- -- ------\n"; for (1 .. $test_size) { my $points = int rand(18000); my $quota = (int rand(8) + 16); $test_data{$_}{points} = $points; $test_data{$_}{quota} = $quota; $test_result{$_} = op_orig($points, $quota); printf ("%5d %2d %2d\n", $points, $quota, $test_result{$_}); } print "\n\n"; # Test each of the alternative compare subs to see if they return the # same values as the original: for (qw(op_cmp2 davidrw_1 davidrw_2 davidrw_2_5 ternary_cmp kutsu)) { test_sub ($_, \&$_); } sub test_sub { my ($name, $func) = @_; for (1 .. $test_size) { my $points = $test_data{$_}{points}; my $quota = $test_data{$_}{quota}; my $return = $func->($points, $quota); unless ($return) { print "$name failed on $points, $quota: no value returned.\n" +; return; } if ($return != $test_result{$_}) { print "$name failed on $points, $quota: returned $return.\n"; return; } } print "$name looks ok\n" } sub op_orig { # OP, original code my ($points, $quota) = @_; if ($points > 18000 && $quota < 24) { return 24; } elsif ($points > 16000 && $quota < 23) { return 23; } elsif ($points > 14000 && $quota < 22) { return 22; } elsif ($points > 12000 && $quota < 21) { return 21; } elsif ($points > 10000 && $quota < 20) { return 20; } elsif ($points > 8000 && $quota < 19) { return 19; } elsif ($points > 6000 && $quota < 18) { return 18; } elsif ($points > 4000 && $quota < 17) { #19 return 17; } elsif ($points > 2000 && $quota < 16) { #17 return 16; } return 15; } sub op_cmp2 { # OP, op_cmp2 my ($points, $quota) = @_; my $base_quota = 15; while($points > 2000 && $quota > $base_quota) { $points -= 2000; $base_quota += 1; } return $base_quota; } sub davidrw_1 { # davidrw suggestion 1 my ($points, $quota) = @_; my @comparisons = ( # points, quota [18000, 24], [16000, 23], [14000, 22], [12000, 21], [10000, 20], [8000, 19], [6000, 18], [4000, 17], [2000, 16], ); foreach my $cmp (@comparisons) { return $cmp->[1] if $points > $cmp->[0] && $quota < $cmp->[1]; } return 15; } sub davidrw_2 { # davidrw suggestion 2 my ($points, $quota) = @_; my @comparisons = map { [($_ - 15) * 2000, $_] } 24 .. 16; foreach my $cmp (@comparisons) { return $cmp->[1] if $points > $cmp->[0] && $quota < $cmp->[1]; } return 15; } sub davidrw_2_5 { # davidrw suggestion 2 as modified by kiat my ($points, $quota) = @_; my @comparisons = map { [($_ - 15) * 2000, $_] } 16 .. 24; foreach my $cmp (@comparisons) { return $cmp->[1] if $points > $cmp->[0] && $quota < $cmp->[1]; } return 15; } sub ternary_cmp { # Just for the fun of it my ($points, $quota) = @_; return ($points > 18000 && $quota < 24) ? 24 : ($points > 16000 && $quota < 23) ? 23 : ($points > 14000 && $quota < 22) ? 22 : ($points > 12000 && $quota < 21) ? 21 : ($points > 10000 && $quota < 20) ? 20 : ($points > 8000 && $quota < 19) ? 19 : ($points > 6000 && $quota < 18) ? 18 : ($points > 4000 && $quota < 17) ? 17 : ($points > 2000 && $quota < 16) ? 16 : 15; } sub kutsu { my ($points, $quota) = @_; my %compare = ( 18000 => 24, 16000 => 23, 14000 => 22, 12000 => 21, 10000 => 20, 8000 => 19, 6000 => 18, 4000 => 17, 2000 => 16, ); for my $key (sort {$b <=> $a} keys %compare) { if ($points > $key and $quota < $compare{$key}) { return $compare{key}; } } return 15; } __END__
Test data:
pts    qt  result
-----  --  ------
 6906  23  15
12199  22  15
17402  17  23
 3470  19  15
16603  19  23
17962  23  15
15762  23  15
 6115  23  15
16711  16  23
 1936  21  15
  870  21  15
 1338  23  15
10537  22  15
14295  18  22
11041  19  20
15167  21  22
16712  17  23
10767  18  20
14383  22  15
  485  20  15
 9298  18  19
 7096  19  15
10030  17  20
11104  20  15
12730  22  15


op_cmp2 failed on 6906, 23: returned 18.
davidrw_1 looks ok
davidrw_2 failed on 17402, 17: returned 15.
davidrw_2_5 failed on 17402, 17: returned 18.
ternary_cmp looks ok
kutsu failed on 17402, 17: no value returned.

In reply to Re^5: alternatives to if and series of elsif by gsiems
in thread alternatives to if and series of elsif by kiat

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.