<?xml version="1.0" encoding="windows-1252"?>
<node id="997139" title="Re: Polish Prefix Calculator" created="2012-10-03 18:13:49" updated="2012-10-03 18:13:49">
<type id="11">
note</type>
<author id="540414">
jwkrahn</author>
<data>
<field name="doctext">
&lt;p&gt;
First, it doesn't seem to work correctly. &amp;nbsp;&amp;nbsp; I tried with the expression &lt;c&gt;(+ 1 2 3 (* 4 3 (- 20 1) (% 5 2)) 3 4)&lt;/c&gt; and got the answer 2221 when it should be 241.
&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;


&lt;blockquote&gt;&lt;i&gt;&lt;c&gt;
sub solvepart($);
...
sub reformat;
...
sub reformat($){
...
sub solvepart($){
&lt;/c&gt;&lt;/i&gt;&lt;/blockquote&gt;
&lt;p&gt;
The declaration for reformat doesn't have a prototype but the definition does even though reformat does not accept any arguments &amp;nbsp;&amp;nbsp; &lt;b&gt;YOU SHOULD NOT USE PROTOTYPES.&lt;/b&gt;
&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;


&lt;blockquote&gt;&lt;i&gt;&lt;c&gt;
	if ($given ~~ /(?:exit)|(?:end)|(?:quit)/i){
...
	if ($VERBOSE or $VERBOSE ~~ /v(?:erbose)?/i){
&lt;/c&gt;&lt;/i&gt;&lt;/blockquote&gt;
&lt;p&gt;
Is there any good reason to use the smartmatch operator (~~) instead of the binding operator (=~)? &amp;nbsp;&amp;nbsp; &lt;c&gt;/(?:exit)|(?:end)|(?:quit)/i&lt;/c&gt; could be written more simply as &lt;c&gt;/exit|end|quit/i&lt;/c&gt;.
&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;


&lt;blockquote&gt;&lt;i&gt;&lt;c&gt;
my $num=qr/(-?\d++\.?\d*?)/;
...
	unshift(@stack, [$2,$3,$4]) while $given =~ s/(.*)\((\S++) ++(-?\d++\.?\d*?) ++(-?\d++\.?\d*?)?\)/$1/;
&lt;/c&gt;&lt;/i&gt;&lt;/blockquote&gt;
&lt;p&gt;
Why define &lt;c&gt;$num&lt;/c&gt; if you are not going to use it?
&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;


&lt;blockquote&gt;&lt;i&gt;&lt;c&gt;
		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);
                }
&lt;/c&gt;&lt;/i&gt;&lt;/blockquote&gt;
&lt;p&gt;
Could be written more simply as:
&lt;/p&gt;
&lt;c&gt;
		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;
                }
&lt;/c&gt;&lt;br /&gt;&lt;br /&gt;



&lt;p&gt;
&lt;b&gt;Update:&lt;/b&gt; this is how I would probably do it:
&lt;/p&gt;
&lt;spoiler&gt;
&lt;c&gt;
#!/usr/bin/perl
use warnings;
use strict;

use Scalar::Util 'looks_like_number';

my $MAXITERATIONS = 500;

while ( &lt;&gt; ) {
    my $iterations = 0;
    1 while s/(\([^()]+\))/ die "MAX ITERATIONS ACHIEVED: ABORTING\n" if ++$iterations &gt;= $MAXITERATIONS; solvepart( $1 ) /eg;
    print "\nANSWER: $_\n\n";
    }

sub solvepart {
    my $expression = shift;
    $expression =~ tr/()//d;
    $expression =~ s/\^/**/;
    my ( $operator, @values ) = split ' ', $expression;
    $operator =~ /\*\*|[+\-*\/%]/ &amp;&amp; @values &gt;= 2 &amp;&amp; @values == grep looks_like_number( $_ ), @values
        or die "IMPROPER INPUT\n";
    eval join $operator, @values;
    }

&lt;/c&gt;
&lt;/spoiler&gt;
</field>
<field name="root_node">
997089</field>
<field name="parent_node">
997089</field>
</data>
</node>
