in reply to How would you solve a user-inputted simple one-variable Linear Equation
For the =, move it to the opposite side of the = by changing its sign and drop the =. Then everything is on one side, and the other side (no longer needed) is 0. (see one of the tweaks: s/(.*)=(.*)/($1)-($2)/; )
Normally I'd use Parse::Yapp for the parsing, but you said no modules. (I just use Data::Dump for debugging.)
#!/usr/bin/perl # http://perlmonks.org/?node_id=1124684 use strict; # hand rolled recursive descent parser using /\G/gc use Data::Dump qw(pp); # anon arrays are [x^0, x^1, x^2, ...] my $variable; @ARGV or @ARGV = split /\n/, <<END; 10x+4=7 3(x+9)=8x 3(x-1)=2x-1 oops = 42 ++ 23 (x-1)(x+1) = 0 2+3x+7(x+27)-6= 23x-45-(145+62-5)x END for ( @ARGV ) { eval # for the die's { $variable = undef; print "\n"; print " raw input: $_\n"; s/\d\K(?=[a-zA-Z])/*/g; # insert missing ops for consistent parse s/(.*)=(.*)/($1)-($2)/; s/ \w+\K (?=\() | \)\K (?=\w) | \)\K (?=\() /*/gx; print "tweaked input: $_\n"; # added default operators my $answer = expr(); /\G\s*\z/gc or error(); # verify complete parse pp "raw answer for $variable ", $answer; defined $variable or die "no variable given"; pop @$answer while @$answer > 2 && $answer->[-1] == 0; # trim trai +ling 0's $answer->[1] or die "variable $variable cancels out"; @$answer > 2 and die "quadratic or higher equation"; print "\n $variable = ", -$answer->[0] / $answer->[1], "\n"; }; $@ and print $@; } sub expr # left associative => term ([+-] term)* { my $left = term(); while( /\G\s*((\+)|-)/gc ) { my $add = $2; my $right = term(); if($add) { $left->[$_] += $right->[$_] for 0..$#$right; } else { $left->[$_] -= $right->[$_] for 0..$#$right; } } return $left; } sub term # left associative => factor (* factor)* { my $left = item(); while( /\G\s*\*/gc ) { my $right = item(); my @result = (0) x (@$left + @$right - 1); my $n = 0; for my $vl (@$left) # cross multiply { my $pos = $n; $result[$pos++] += $vl * $_ for @$right; $n++; } pop @result while @result > 2 && $result[-1] == 0; # trim trailing + 0's $left = [ @result ]; } return $left; } sub item # parens or number or variable or unary minus { if( /\G\s*\(/gc ) { my $val = expr(); return /\G\s*\)/gc ? $val : error(); # must have closing paren } /\G\s*((\d+(\.\d*)?|\.\d+))/gc and return [ $1, 0 ]; if( /\G\s*(\w+)/gc ) { defined $variable && $variable ne $1 and die "more than one variable used '$variable' and '$1'"; $variable = $1; return [ 0, 1 ]; } if( /\G\s*-/gc ) # unary minus { my $right = item(); return [ map -$_, @$right ]; } error(); } sub error { s/\G/ SYNTAX ERROR->/; die "$_\n"; }
|
---|
Replies are listed 'Best First'. | |
---|---|
Re^2: How would you solve a user-inputted simple one-variable Linear Equation
by Anonymous Monk on Apr 26, 2015 at 02:47 UTC | |
Re^2: How would you solve a user-inputted simple one-variable Linear Equation
by nat47 (Sexton) on Apr 26, 2015 at 12:54 UTC | |
by Anonymous Monk on Apr 26, 2015 at 20:19 UTC |