http://qs1969.pair.com?node_id=431278


in reply to Perl and maths

Here are the beginnings of a brief skeleton of an evaluator for simple (and fully parenthesized) arithmetic expressions to get you started. It prints out all of the intermediate steps before it gets to the final answer. You'd need to swizzle the results around to get exactly what you wanted, but I think you get the idea...
((1+2)+((3+4)+(5*6)))
1 + 2 = 3
3 + 4 = 7
5 * 6 = 30
7 + 30 = 37
3 + 37 = 40
Final Answer: 40
#!/usr/bin/perl -w # # Evaluate simplified arithmetic expressions # use re 'eval'; #use recursive regex for parsing use strict; our $num = qr{\d+}; our $op = qr{[+*/\-]}; # an expression is a number or a pair of expressions separated by # an operator, enclosed in parens. our $exp; $exp = qr{$num|\(\s*(??{$exp})\s*$op\s*(??{$exp})\s*\)}s; # Something to test the evaluator with my @tests = ("(1+2)","((3+4)+(5+6))","((1+2)+((3+4)+(5*6)))"); for my $t (@tests) { print "$t\n"; print "Final Answer: ", simplify($t); print "\n\n"; } sub simplify { my $e = shift; if($e =~ /^($num)$/s) { return $1; } elsif ($e =~ /^\(($exp)\+($exp)\)$/s) { my ($l, $r) = ($1,$2); my $left = simplify($l); my $right = simplify($r); my $sum = $left + $right; # You'll need to do more here if # you're doing fractions. print "$left + $right = $sum\n"; return "$sum"; } elsif ($e =~ /^\(($exp)-($exp)\)$/s) { #subtraction } elsif ($e =~ /^\(($exp)\*($exp)\)$/s) { my ($l, $r) = ($1,$2); my $left = simplify($l); my $right = simplify($r); my $prod = $left * $right; print "$left * $right = $prod\n"; return "$prod"; } elsif ($e =~ /^\(($exp)\/($exp)\)$/s) { #division } else { die "Syntax error\n"; } }


-- All code is 100% tested and functional unless otherwise noted.