Beefy Boxes and Bandwidth Generously Provided by pair Networks
The stupid question is the question not asked
 
PerlMonks  

Some simple math and absolute values

by sidmuchrock (Novice)
on May 23, 2020 at 01:55 UTC ( #11117138=perlquestion: print w/replies, xml ) Need Help??

sidmuchrock has asked for the wisdom of the Perl Monks concerning the following question:

I'm wondering how to do this better than my 4 line method. Feels like I'm missing something obvious. But example code below works Basically I want to show weight * price = total but allow a minimum weight but if it's a negative weight it should be the reverse of the above Expected results: 2.3 = $23 .3 = $10 0 = $10 -.3 = -$10 -2.3 = -$23
$wt = $ARGV[0]; $min = 1; $price = 10; while ($wt ne '') { $nwt = abs($wt); $nwt = $min if $nwt<$min; $total = $nwt*$price; $total = -$total if $wt<0; print "Price: $total\n"; print "Next Weight: "; chomp($wt = <stdin>); }

Replies are listed 'Best First'.
Re: Some simple math and absolute values (updated)
by haukex (Chancellor) on May 23, 2020 at 07:56 UTC

    TIMTOWTDI...

    use warnings; use strict; our $MIN = 1; our $PFACT = 10; sub price { my $weight = shift; return abs $weight < $MIN ? ( $weight < 0 ? -$PFACT : $PFACT ) : $PFACT * $weight; } use Test::More; is price($$_[0]), $$_[1] for [ 5.0, 50],[ 2.3, 23],[ 1.1, 11],[ 1, 10],[ 0.3, 10],[0,10], [-5.0,-50],[-2.3,-23],[-1.1,-11],[-1,-10],[-0.3,-10]; { local $MIN = 3; is price($$_[0]), $$_[1] for [ 5.0, 50],[ 2.3, 10],[ 1.1, 10],[ 1, 10],[ 0.3, 10],[0,10], [-5.0,-50],[-2.3,-10],[-1.1,-10],[-1,-10],[-0.3,-10]; } { local $PFACT = 5; is price($$_[0]), $$_[1] for [ 5.0, 25],[ 2.3, 11.5],[ 1.1, 5.5],[ 1, 5],[ 0.3, 5],[0,5], [-5.0,-25],[-2.3,-11.5],[-1.1,-5.5],[-1,-5],[-0.3,-5]; } { local ($MIN,$PFACT) = (3,5); is price($$_[0]), $$_[1] for [ 5.0, 25],[ 2.3, 5],[ 1.1, 5],[ 1, 5],[ 0.3, 5],[0,5], [-5.0,-25],[-2.3,-5],[-1.1,-5],[-1,-5],[-0.3,-5]; } done_testing;

    Update: Expanded test cases. Please check if this is what you want, keeping in mind the caveat that jo37 mentioned!

      Which can be "golfed" to
      $PFACT * ($weight, ($weight >= 0) * 2 - 1)[abs $weight < $MIN]

      map{substr$_->[0],$_->[1]||0,1}[\*||{},3],[[]],[ref qr-1,-,-1],[{}],[sub{}^*ARGV,3]
Re: Some simple math and absolute values
by jo37 (Monk) on May 23, 2020 at 12:03 UTC

    The values in the given example have one small flaw:
    As $min is one, some code would pass a test even if it didn't calculate $min * $price but used $price instead.

    Greetings,
    -jo

    $gryYup$d0ylprbpriprrYpkJl2xyl~rzg??P~5lp2hyl0p$
Re: Some simple math and absolute values
by parv (Vicar) on May 23, 2020 at 06:48 UTC

    Could reduce to 2 statements, does not seem any better ...

    $nwt = abs( $wt ); $total = ( $nwt < $min ? $min : $nwt ) * $price * ( $wt < 0 ? -1 : 1 ) ;
Re: Some simple math and absolute values
by BillKSmith (Prior) on May 23, 2020 at 23:37 UTC
    The following code may not be any shorter than yours, but I find it much easier to understand. The tests demonstrate that it produces the same total as yours for a variety of weights.
    use strict; use warnings; use Test::More tests => 11; my $min = 1; my $price = 10; sub total { my $wt = $_[0]; my $Total = ($wt < -$min) ? $price * $wt : ($wt < 0 ) ? $price * (-$min) : ($wt < $min ) ? $price * $min : $price * $wt ; return $Total; } sub refrence { my $wt = $_[0]; my $nwt = abs($wt); $nwt = $min if $nwt<$min; my $total = $nwt*$price; $total = -$total if $wt<0; return $total; } for (0..10) { my $trial_wt = .3 * ($_ -5); is( total($trial_wt), refrence($trial_wt), "Weight: $trial_wt"); }

    OUTPUT:

    1..11 ok 1 - Weight: -1.5 ok 2 - Weight: -1.2 ok 3 - Weight: -0.9 ok 4 - Weight: -0.6 ok 5 - Weight: -0.3 ok 6 - Weight: 0 ok 7 - Weight: 0.3 ok 8 - Weight: 0.6 ok 9 - Weight: 0.9 ok 10 - Weight: 1.2 ok 11 - Weight: 1.5
    Bill
Re: Some simple math and absolute values
by syphilis (Bishop) on May 23, 2020 at 02:19 UTC
    Hi,

    I think this will do the same:
    Update: No, it fails to do the right thing for negative $wt values greater than -1.
    $wt = $ARGV[0]; $min = 1; $price = 10; while ($wt ne '') { $wt = $min if abs($wt)< $min; print "Price: " $wt * $price, "\n"; print "Next Weight: "; chomp($wt = <stdin>); }
    Cheers,
    Rob
Re: Some simple math and absolute values
by 1nickt (Abbot) on May 23, 2020 at 03:20 UTC

    Hi,

    I am not a math expert nor an algorithm expert nor a golfer, Perl or otherwise, but maybe something like this?

    my $price = ($wt || 1) * 10; $price = 10 * $price/abs($price) if abs($price) < 10;

    Output:

    perl blrg.pl 2.3 Price: 23 Next Weight: .3 Price: 10 Next Weight: 0 Price: 10 Next Weight: -.3 Price: -10 Next Weight: -2.3 Price: -23 Next Weight:

    Hope this helps!


    The way forward always starts with a minimal test.
      This was what I was missing last night! I kept trying to say if $wt/abs($wt) and it was dying in the 0 case, but by turning the 0 to $min in the possible total and then checking $total/abs($total) that solved. it. Thank you.
      $total = ($wt || $min) * $price; $total = $total/abs($total) * $price * $min if abs($wt) < $min +;

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://11117138]
Approved by 1nickt
Front-paged by 1nickt
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others taking refuge in the Monastery: (6)
As of 2020-06-05 11:03 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    Do you really want to know if there is extraterrestrial life?



    Results (37 votes). Check out past polls.

    Notices?