Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- <?php
- /**
- * Return answer, operator precedence must be retained. / * - + is the order.
- * @param unknown $s
- */
- function calc($sum){
- // No requirement for handling parenthesis here,
- // but I'll do it anyway because I like recursion :)
- $sIX=0;
- $moreBrackets=true;
- // Always work out sums in brackets first, from deepest to most shallow
- while($moreBrackets){
- $l=strlen($sum);
- $moreBrackets=false;
- for($n=0;$n<$l;$n++){
- if($sum{$n}=='('){
- $moreBrackets=true;
- $sIX=$n;
- }
- if($sum{$n}==')'){
- if(!$moreBrackets){
- return "Error, no opening bracket for closing bracket!";
- }
- // Could obviously combine these 3 lines into 1,
- // but I'll pay lip service to readability...
- $subSum=substr($sum,$sIX+1,$n-$sIX-1);
- $newSum=substr($sum,0,$sIX).calc($subSum).substr($sum,$n+1);
- $sum=$newSum;
- break;
- }
- }
- }
- $ops="/*-+";
- $result=0;
- $gotOperator=false;
- if($sum{0}=='-')
- $sum{0}='N';
- for($n=0;$n<strlen($ops);$n++)
- $sum=str_replace($ops{$n}.'-',$ops{$n}."N",$sum);
- for($n=0;$n<strlen($ops);$n++){
- $op=$ops{$n};
- $ix=1;
- while($ix!==false){
- $ix=strpos($sum,$op);
- $len=strlen($sum);
- if($ix!==false){
- $gotOperator=true;
- if($ix==0||$ix==$len-1){
- return "Error, operator not enclosed by digits";
- }
- $s=$ix-1;
- $e=$ix+1;
- // Find start of lhs value
- while($s>-1 && (($sum{$s}>='0' && $sum{$s}<='9') || ($sum{$s}=='.' || $sum{$s}=='N')))
- --$s;
- // Find end of rhs value
- while($e<$len && (($sum{$e}>='0' && $sum{$e}<='9') || ($sum{$e}=='.' || $sum{$e}=='N')))
- ++$e;
- ++$s;
- --$e;
- // Check for negative values and decimals with no leading digit
- $v0=substr($sum,$s,$ix-$s);
- if($v0{0}=='.')
- $v0='0'.$v0;
- else if($v0{0}=='N')
- $v0{0}='-';
- $v1=substr($sum,$ix+1,$e-$ix);
- if($v1{0}=='.')
- $v1='0'.$v1;
- else if($v1{0}=='N')
- $v1{0}='-';
- switch($op){
- case '/':
- $result=$v0/$v1;
- break;
- case '*':
- $result=$v0*$v1;
- break;
- case '-':
- $result=$v0-$v1;
- break;
- case '+':
- $result=$v0+$v1;
- break;
- }
- if($result<0)
- $result='N'.(-$result);
- $newSum=substr($sum,0,$s).$result.substr($sum,$ix+1+($e-$ix));
- $sum=$newSum;
- }
- }
- }
- if($sum{0}=='N')
- $sum{0}='-';
- return $sum;
- }
- header('Content-type:text/plain');
- // Should print 100
- print calc("10*10")."\n";
- // Should print 19
- print calc("20+-1")."\n";
- // Should print 3
- print calc("3*3/3")."\n";
- // Should print -1180
- print calc("-100*23/2+-30")."\n";
- // Should print 8
- print calc("2+3*2")."\n";
- // Should print 6
- print calc("2+2+2")."\n";
- /** Bonus points :) **/
- // Should print 25
- print calc("5*(2+3)")."\n";
- // Should print 2
- print calc("((10/5)+(4/2))/(1+1+1-1)")."\n";
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement