in reply to
Re: Perl and maths

in thread Perl and maths

Here's a modification to my code above which handles adding fractions and printing out the partial results. Finishing it off is left as an exercise to the reader...

`
(1/2+2/3)`

7/6

(1/2+(2/3+4/5))

(1/2+22/15)

59/30

((5/3+7/13)+(5/2+3/7))

(86/39+(5/2+3/7))

(86/39+41/14)

2803/546

`#!/usr/bin/perl -w
#
# add fractions and display partial results
#
use re 'eval'; #use recursive regex for parsing
use strict;
our $num = qr{\d+(?:/\d+)?};
our $op = qr{[+*/\-]};
# an expression is a fraction 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+2/3)","(1/2+(2/3+4/5))","((5/3+7/13)+(5/2+3/7))");
for my $t (@tests)
{
print "$t\n";
print simplify($t,"","");
print "\n\n";
}
sub simplify
{
my ($e, $pre, $post) = @_;
if($e =~ /^($num)$/s)
{
return $1;
}
elsif ($e =~ /^\(($exp)\+($exp)\)$/s)
{
my ($l, $r) = ($1,$2);
my $left = simplify($l,"","");
print "$pre($left+$r)$post\n" if $l!~m/^$num$/;
my $right = simplify($r,"($left+",")");
print "$pre($left+$right)$post\n" if $r!~m/^$num$/;
my $sum = add_frac($left, $right);
return "$sum";
}
elsif ($e =~ /^\(($exp)-($exp)\)$/s)
{
#subtraction
}
elsif ($e =~ /^\(($exp)\*($exp)\)$/s)
{
#multiplication
}
elsif ($e =~ /^\(($exp)\/($exp)\)$/s)
{
#division
}
else
{
die "Syntax error\n";
}
}
sub add_frac
{
my ($l, $r) = @_;
my ($l_num, $l_denom) = $l =~ m{(\d+)/(\d+)};
my ($r_num, $r_denom) = $r =~ m{(\d+)/(\d+)};
my $denom = $l_denom * $r_denom;
my $ans = $l_num * $r_denom + $r_num * $l_denom;
return "$ans/$denom";
}
`

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