Last active
March 27, 2025 17:32
-
-
Save theking2/0f3184ba8f4a9fd604d8e9cfeb64fbc9 to your computer and use it in GitHub Desktop.
Polish notation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* Polish notation | |
* @param $expression - Space seperated operators and param indices | |
* @param $param - two or more params for the calculation | |
*/ | |
function pn(string $expression, mixed ...$param) { | |
$operators = "+-*/%"; $delimiter = " "; | |
$expression = explode($delimiter, $expression); | |
$stack = []; | |
do { | |
$itm=array_pop($expression); | |
if( !strstr($operators, $itm) ) { // treat everything not an operator as operand | |
if( !ctype_digit( $itm ) ) { | |
throw new \InvalidArgumentException( "Operand index not integer: $itm\n" ); | |
} | |
if(! (0 <= $itm and $itm < count( $param )) ) { | |
throw new \OutOfBoundsException ( "Operand index out of range: $itm\n" ); | |
} | |
if( !is_numeric( $param[$itm] ) ) { | |
throw new \InvalidArgumentException( "Operand not numeric: $param[$itm]\n" ); | |
} | |
array_push($stack, $param[$itm]); | |
continue; | |
} | |
// we have an operator | |
switch($itm) { | |
case '+': array_push( $stack, array_pop($stack) + array_pop($stack) ); break; | |
case '-': array_push( $stack, array_pop($stack) - array_pop($stack) ); break; | |
case '*': array_push( $stack, array_pop($stack) * array_pop($stack) ); break; | |
case '/': array_push( $stack, array_pop($stack) / array_pop($stack) ); break; | |
case '%': array_push( $stack, array_pop($stack) % array_pop($stack) ); break; | |
//default: throw new \InvalidArgumentException( "Unknown operator $itm" ); | |
} | |
} while ($expression); | |
return array_pop($stack); | |
} | |
// Parameters are indexed from 0 upwards | |
try{ | |
echo pn("/ + 3 0 / 2 1", 30, 40, 50, 69), "\n"; | |
} catch( Exception $e) {echo $e->getMessage();} | |
try{ | |
echo pn("/ + 3 0 / 2 1", 30, 40, 50), "\n"; | |
} catch( Exception $e) {echo $e->getMessage();} | |
try{ | |
echo pn("/ + 3 3 / 2 1.1", 30, 40, 50, "a"), "\n"; | |
} catch( Exception $e) {echo $e->getMessage();} | |
try{ | |
echo pn("/ + 3 3 / 2 1", 30, 40, 50, "a"), "\n"; | |
} catch( Exception $e) {echo $e->getMessage();} | |
// If parameters are in an array already use unpacking | |
$operants = [3, 4, 5, 6]; | |
$expresion = "/ + 0 1 / 2 3"; | |
echo pn($expresion, ...$operants), "\n"; |
FSR
Make this into a class to
- be able to (not) reverse
- be able to specify a delimiter other than
' '
- checking of a parameters and better exception handling.
- custom operators (add swap, dup(icate), drop
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
for a rpn remove thearray_reverse()
for a rpn use
array_shift()
in line 13or use a
foreach($expression as $itm)
;