Beefy Boxes and Bandwidth Generously Provided by pair Networks
Pathologically Eclectic Rubbish Lister

Re: Polish Prefix Calculator

by jwkrahn (Monsignor)
on Oct 03, 2012 at 22:13 UTC ( #997139=note: print w/replies, xml ) Need Help??

in reply to Polish Prefix Calculator

First, it doesn't seem to work correctly.    I tried with the expression (+ 1 2 3 (* 4 3 (- 20 1) (% 5 2)) 3 4) and got the answer 2221 when it should be 241.

sub solvepart($); ... sub reformat; ... sub reformat($){ ... sub solvepart($){

The declaration for reformat doesn't have a prototype but the definition does even though reformat does not accept any arguments    YOU SHOULD NOT USE PROTOTYPES.

if ($given ~~ /(?:exit)|(?:end)|(?:quit)/i){ ... if ($VERBOSE or $VERBOSE ~~ /v(?:erbose)?/i){

Is there any good reason to use the smartmatch operator (~~) instead of the binding operator (=~)?    /(?:exit)|(?:end)|(?:quit)/i could be written more simply as /exit|end|quit/i.

my $num=qr/(-?\d++\.?\d*?)/; ... unshift(@stack, [$2,$3,$4]) while $given =~ s/(.*)\((\S++) ++(-?\d +++\.?\d*?) ++(-?\d++\.?\d*?)?\)/$1/;

Why define $num if you are not going to use it?

if ($level[0]eq'+'){ $level[2] ?($value=$level[1]+$level[2]) :($value+=$level[1]); } elsif ($level[0]eq'-'){ $level[2] ?($value=$level[1]-$level[2]) :($value=$level[1]-$value); } elsif ($level[0]eq'/'){ $level[2] ?($value=$level[1]/$level[2]) :($value=$level[1]/$value); } elsif ($level[0]eq'*'){ $level[2] ?($value=$level[1]*$level[2]) :($value*=$level[1]); } elsif ($level[0]eq'**'or$level[0]eq'^'){ $level[2] ?($value=$level[1]**$level[2]) :($value=$level[1]**$value); } elsif ($level[0]eq'%'){ $level[2] ?($value=$level[1] % $level[2]) :($value=$level[1] % $value); }

Could be written more simply as:

if ($level[0]eq'+'){ $value = $level[1] + $level[2] || $value; } elsif ($level[0]eq'-'){ $value = $level[1] - $level[2] || $value; } elsif ($level[0]eq'/'){ $value = $level[1] / $level[2] || $value; } elsif ($level[0]eq'*'){ $value = $level[1] * $level[2] || $value; } elsif ($level[0]eq'**'or$level[0]eq'^'){ $value = $level[1] ** $level[2] || $value; } elsif ($level[0]eq'%'){ $value = $level[1] % $level[2] || $value; }

Update: this is how I would probably do it:

#!/usr/bin/perl use warnings; use strict; use Scalar::Util 'looks_like_number'; my $MAXITERATIONS = 500; while ( <> ) { my $iterations = 0; 1 while s/(\([^()]+\))/ die "MAX ITERATIONS ACHIEVED: ABORTING\n" +if ++$iterations >= $MAXITERATIONS; solvepart( $1 ) /eg; print "\nANSWER: $_\n\n"; } sub solvepart { my $expression = shift; $expression =~ tr/()//d; $expression =~ s/\^/**/; my ( $operator, @values ) = split ' ', $expression; $operator =~ /\*\*|[+\-*\/%]/ && @values >= 2 && @values == grep l +ooks_like_number( $_ ), @values or die "IMPROPER INPUT\n"; eval join $operator, @values; }

Replies are listed 'Best First'.
Re^2: Polish Prefix Calculator
by protist (Monk) on Oct 04, 2012 at 07:04 UTC

    I edited the reformat subroutine so that it now properly handles the input you described. Thank you for pointing out that bug. :)

    I can see no reason to not (italics) use ~~

    Whenever I put $num in that particular line of code, it would store $4 in $3 for some reason. Eventually since I already had it written and working, I decided to not fix what wasn't broken. Maybe I'll change it later.

    I removed the useless (?:) groupings you described. It is worth mentioning that my regex for verbose contains redundancies, but intentionally so for the sake of being explicit.

    I like your eval join part, but I think you will find the parsing this problem requires is much more involved than tr/()//

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://997139]
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others musing on the Monastery: (5)
As of 2018-06-20 05:00 GMT
Find Nodes?
    Voting Booth?
    Should cpanminus be part of the standard Perl release?

    Results (116 votes). Check out past polls.