tasks a-s
This commit is contained in:
parent
47bf37c096
commit
b83f433714
12433 changed files with 156208 additions and 123 deletions
14
Task/Parsing-RPN-calculator-algorithm/0DESCRIPTION
Normal file
14
Task/Parsing-RPN-calculator-algorithm/0DESCRIPTION
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
Create a stack-based evaluator for an expression in [[wp:Reverse Polish notation|reverse Polish notation]] that also shows the changes in the stack
|
||||
as each individual token is processed ''as a table''.
|
||||
|
||||
* Assume an input of a correct, space separated, string of tokens of an RPN expression
|
||||
* Test with the RPN expression generated from the [[Parsing/Shunting-yard algorithm]] task <code>'3 4 2 * 1 5 - 2 3 ^ ^ / +'</code> then print and display the output here.
|
||||
|
||||
;Note:
|
||||
* '^' means exponentiation in the expression above.
|
||||
|
||||
;See also:
|
||||
* [[Parsing/Shunting-yard algorithm]] for a method of generating an RPN from an infix expression.
|
||||
* Several solutions to [[24 game/Solve]] make use of RPN evaluators (although tracing how they work is not a part of that task).
|
||||
* [[Parsing/RPN to infix conversion]].
|
||||
* [[Arithmetic evaluation]].
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
grammar rpnC ;
|
||||
//
|
||||
// rpn Calculator
|
||||
//
|
||||
// Nigel Galloway - April 7th., 2012
|
||||
//
|
||||
@members {
|
||||
Stack<Double> s = new Stack<Double>();
|
||||
}
|
||||
rpn : (WS* (num|op) (WS | WS* NEWLINE {System.out.println(s.pop());}))*;
|
||||
num : '-'? Digit+ ('.' Digit+)? {s.push(Double.parseDouble($num.text));};
|
||||
Digit : '0'..'9';
|
||||
op : '-' {double x = s.pop(); s.push(s.pop() - x);}
|
||||
| '/' {double x = s.pop(); s.push(s.pop() / x);}
|
||||
| '*' {s.push(s.pop() * s.pop());}
|
||||
| '^' {double x = s.pop(); s.push(Math.pow(s.pop(), x));}
|
||||
| '+' {s.push(s.pop() + s.pop());};
|
||||
WS : (' ' | '\t'){skip()};
|
||||
NEWLINE : '\r'? '\n';
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
with Ada.Text_IO, Ada.Containers.Vectors;
|
||||
|
||||
procedure RPN_Calculator is
|
||||
|
||||
package IIO is new Ada.Text_IO.Float_IO(Float);
|
||||
|
||||
package Float_Vec is new Ada.Containers.Vectors
|
||||
(Index_Type => Positive, Element_Type => Float);
|
||||
Stack: Float_Vec.Vector;
|
||||
|
||||
Input: String := Ada.Text_IO.Get_Line;
|
||||
Cursor: Positive := Input'First;
|
||||
New_Cursor: Positive;
|
||||
|
||||
begin
|
||||
loop
|
||||
-- read spaces
|
||||
while Cursor <= Input'Last and then Input(Cursor)=' ' loop
|
||||
Cursor := Cursor + 1;
|
||||
end loop;
|
||||
|
||||
exit when Cursor > Input'Last;
|
||||
|
||||
New_Cursor := Cursor;
|
||||
while New_Cursor <= Input'Last and then Input(New_Cursor) /= ' ' loop
|
||||
New_Cursor := New_Cursor + 1;
|
||||
end loop;
|
||||
|
||||
-- try to read a number and push it to the stack
|
||||
declare
|
||||
Last: Positive;
|
||||
Value: Float;
|
||||
X, Y: Float;
|
||||
begin
|
||||
IIO.Get(From => Input(Cursor .. New_Cursor - 1),
|
||||
Item => Value,
|
||||
Last => Last);
|
||||
Stack.Append(Value);
|
||||
Cursor := New_Cursor;
|
||||
|
||||
exception -- if reading the number fails, try to read an operator token
|
||||
when others =>
|
||||
Y := Stack.Last_Element; Stack.Delete_Last; -- pick two elements
|
||||
X := Stack.Last_Element; Stack.Delete_Last; -- from the stack
|
||||
case Input(Cursor) is
|
||||
when '+' => Stack.Append(X+Y);
|
||||
when '-' => Stack.Append(X-Y);
|
||||
when '*' => Stack.Append(X*Y);
|
||||
when '/' => Stack.Append(X/Y);
|
||||
when '^' => Stack.Append(X ** Integer(Float'Rounding(Y)));
|
||||
when others => raise Program_Error with "unecpected token '"
|
||||
& Input(Cursor) & "' at column" & Integer'Image(Cursor);
|
||||
end case;
|
||||
Cursor := New_Cursor;
|
||||
end;
|
||||
|
||||
for I in Stack.First_Index .. Stack.Last_Index loop
|
||||
Ada.Text_IO.Put(" ");
|
||||
IIO.Put(Stack.Element(I), Aft => 5, Exp => 0);
|
||||
end loop;
|
||||
Ada.Text_IO.New_Line;
|
||||
end loop;
|
||||
|
||||
Ada.Text_IO.Put("Result = ");
|
||||
IIO.Put(Item => Stack.Last_Element, Aft => 5, Exp => 0);
|
||||
|
||||
|
||||
end RPN_Calculator;
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
evalRPN("3 4 2 * 1 5 - 2 3 ^ ^ / +")
|
||||
evalRPN(s){
|
||||
stack := []
|
||||
out := "For RPN expression: '" s "'`r`n`r`nTOKEN`t`tACTION`t`t`tSTACK`r`n"
|
||||
Loop Parse, s
|
||||
If A_LoopField is number
|
||||
t .= A_LoopField
|
||||
else
|
||||
{
|
||||
If t
|
||||
stack.Insert(t)
|
||||
, out .= t "`tPush num onto top of stack`t" stackShow(stack) "`r`n"
|
||||
, t := ""
|
||||
If InStr("+-/*^", l := A_LoopField)
|
||||
{
|
||||
a := stack.Remove(), b := stack.Remove()
|
||||
stack.Insert( l = "+" ? b + a
|
||||
:l = "-" ? b - a
|
||||
:l = "*" ? b * a
|
||||
:l = "/" ? b / a
|
||||
:l = "^" ? b **a
|
||||
:0 )
|
||||
out .= l "`tApply op " l " to top of stack`t" stackShow(stack) "`r`n"
|
||||
}
|
||||
}
|
||||
r := stack.Remove()
|
||||
out .= "`r`n The final output value is: '" r "'"
|
||||
clipboard := out
|
||||
return r
|
||||
}
|
||||
StackShow(stack){
|
||||
for each, value in stack
|
||||
out .= A_Space value
|
||||
return subStr(out, 2)
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
@% = &60B
|
||||
RPN$ = "3 4 2 * 1 5 - 2 3 ^ ^ / +"
|
||||
|
||||
DIM Stack(1000)
|
||||
SP% = 0
|
||||
|
||||
FOR i% = 1 TO LEN(RPN$)
|
||||
Token$ = MID$(RPN$,i%,1)
|
||||
IF Token$ <> " " THEN
|
||||
PRINT Token$ " :";
|
||||
CASE Token$ OF
|
||||
WHEN "+": PROCpush(FNpop + FNpop)
|
||||
WHEN "-": PROCpush(-FNpop + FNpop)
|
||||
WHEN "*": PROCpush(FNpop * FNpop)
|
||||
WHEN "/": n = FNpop : PROCpush(FNpop / n)
|
||||
WHEN "^": n = FNpop : PROCpush(FNpop ^ n)
|
||||
WHEN "0","1","2","3","4","5","6","7","8","9":
|
||||
PROCpush(VALMID$(RPN$,i%))
|
||||
WHILE ASCMID$(RPN$,i%)>=48 AND ASCMID$(RPN$,1)<=57
|
||||
i% += 1
|
||||
ENDWHILE
|
||||
ENDCASE
|
||||
FOR j% = SP%-1 TO 0 STEP -1 : PRINT Stack(j%); : NEXT
|
||||
PRINT
|
||||
ENDIF
|
||||
NEXT i%
|
||||
END
|
||||
|
||||
DEF PROCpush(n)
|
||||
IF SP% > DIM(Stack(),1) ERROR 100, "Stack full"
|
||||
Stack(SP%) = n
|
||||
SP% += 1
|
||||
ENDPROC
|
||||
|
||||
DEF FNpop
|
||||
IF SP% = 0 ERROR 100, "Stack empty"
|
||||
SP% -= 1
|
||||
= Stack(SP%)
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
#include <vector>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
#include <cmath>
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
#include <cstdlib>
|
||||
|
||||
double rpn(const std::string &expr){
|
||||
std::istringstream iss(expr);
|
||||
std::vector<double> stack;
|
||||
std::cout << "Input\tOperation\tStack after" << std::endl;
|
||||
std::string token;
|
||||
while (iss >> token) {
|
||||
std::cout << token << "\t";
|
||||
double tokenNum;
|
||||
if (std::istringstream(token) >> tokenNum) {
|
||||
std::cout << "Push\t\t";
|
||||
stack.push_back(tokenNum);
|
||||
} else {
|
||||
std::cout << "Operate\t\t";
|
||||
double secondOperand = stack.back();
|
||||
stack.pop_back();
|
||||
double firstOperand = stack.back();
|
||||
stack.pop_back();
|
||||
if (token == "*")
|
||||
stack.push_back(firstOperand * secondOperand);
|
||||
else if (token == "/")
|
||||
stack.push_back(firstOperand / secondOperand);
|
||||
else if (token == "-")
|
||||
stack.push_back(firstOperand - secondOperand);
|
||||
else if (token == "+")
|
||||
stack.push_back(firstOperand + secondOperand);
|
||||
else if (token == "^")
|
||||
stack.push_back(std::pow(firstOperand, secondOperand));
|
||||
else { //just in case
|
||||
std::cerr << "Error" << std::endl;
|
||||
std::exit(1);
|
||||
}
|
||||
}
|
||||
std::copy(stack.begin(), stack.end(), std::ostream_iterator<double>(std::cout, " "));
|
||||
std::cout << std::endl;
|
||||
}
|
||||
return stack.back();
|
||||
}
|
||||
|
||||
int main() {
|
||||
std::string s = " 3 4 2 * 1 5 - 2 3 ^ ^ / + ";
|
||||
std::cout << "Final answer: " << rpn(s) << std::endl;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
void die(const char *msg)
|
||||
{
|
||||
fprintf(stderr, "%s", msg);
|
||||
abort();
|
||||
}
|
||||
|
||||
#define MAX_D 256
|
||||
double stack[MAX_D];
|
||||
int depth;
|
||||
|
||||
void push(double v)
|
||||
{
|
||||
if (depth >= MAX_D) die("stack overflow\n");
|
||||
stack[depth++] = v;
|
||||
}
|
||||
|
||||
double pop()
|
||||
{
|
||||
if (!depth) die("stack underflow\n");
|
||||
return stack[--depth];
|
||||
}
|
||||
|
||||
double rpn(char *s)
|
||||
{
|
||||
double a, b;
|
||||
int i;
|
||||
char *e, *w = " \t\n\r\f";
|
||||
|
||||
for (s = strtok(s, w); s; s = strtok(0, w)) {
|
||||
a = strtod(s, &e);
|
||||
if (e > s) printf(" :"), push(a);
|
||||
#define binop(x) printf("%c:", *s), b = pop(), a = pop(), push(x)
|
||||
else if (*s == '+') binop(a + b);
|
||||
else if (*s == '-') binop(a - b);
|
||||
else if (*s == '*') binop(a * b);
|
||||
else if (*s == '/') binop(a / b);
|
||||
else if (*s == '^') binop(pow(a, b));
|
||||
#undef binop
|
||||
else {
|
||||
fprintf(stderr, "'%c': ", *s);
|
||||
die("unknown oeprator\n");
|
||||
}
|
||||
for (i = depth; i-- || 0 * putchar('\n'); )
|
||||
printf(" %g", stack[i]);
|
||||
}
|
||||
|
||||
if (depth != 1) die("stack leftover\n");
|
||||
|
||||
return pop();
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
char s[] = " 3 4 2 * 1 5 - 2 3 ^ ^ / + ";
|
||||
printf("%g\n", rpn(s));
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
#define die(msg) fprintf(stderr, msg"\n"), abort();
|
||||
double get(const char *s, const char *e, char **new_e)
|
||||
{
|
||||
const char *t;
|
||||
double a, b;
|
||||
|
||||
for (e--; e >= s && isspace(*e); e--);
|
||||
for (t = e; t > s && !isspace(t[-1]); t--);
|
||||
|
||||
if (t < s) die("underflow");
|
||||
|
||||
#define get2(expr) b = get(s, t, (char **)&t), a = get(s, t, (char **)&t), a = expr
|
||||
a = strtod(t, (char **)&e);
|
||||
if (e <= t) {
|
||||
if (t[0] == '+') get2(a + b);
|
||||
else if (t[0] == '-') get2(a - b);
|
||||
else if (t[0] == '*') get2(a * b);
|
||||
else if (t[0] == '/') get2(a / b);
|
||||
else if (t[0] == '^') get2(pow(a, b));
|
||||
else {
|
||||
fprintf(stderr, "'%c': ", t[0]);
|
||||
die("unknown token");
|
||||
}
|
||||
}
|
||||
#undef get2
|
||||
|
||||
*(const char **)new_e = t;
|
||||
return a;
|
||||
}
|
||||
|
||||
double rpn(const char *s)
|
||||
{
|
||||
const char *e = s + strlen(s);
|
||||
double v = get(s, e, (char**)&e);
|
||||
|
||||
while (e > s && isspace(e[-1])) e--;
|
||||
if (e == s) return v;
|
||||
|
||||
fprintf(stderr, "\"%.*s\": ", e - s, s);
|
||||
die("front garbage");
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
printf("%g\n", rpn("3 4 2 * 1 5 - 2 3 ^ ^ / +"));
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
(ns rosettacode.parsing-rpn-calculator-algorithm
|
||||
(:require clojure.math.numeric-tower
|
||||
clojure.string
|
||||
clojure.pprint))
|
||||
|
||||
(def operators
|
||||
"the only allowable operators for our calculator"
|
||||
{"+" +
|
||||
"-" -
|
||||
"*" *
|
||||
"/" /
|
||||
"^" clojure.math.numeric-tower/expt})
|
||||
|
||||
(defn rpn
|
||||
"takes a string and returns a lazy-seq of all the stacks"
|
||||
[string]
|
||||
(letfn [(rpn-reducer [stack item] ; this takes a stack and one item and makes a new stack
|
||||
(if (contains? operators item)
|
||||
(let [operand-1 (peek stack) ; if we used lists instead of vectors, we could use destructuring, but stacks would look backwards
|
||||
stack-1 (pop stack)] ;we're assuming that all the operators are binary
|
||||
(conj (pop stack-1)
|
||||
((operators item) (peek stack-1) operand-1)))
|
||||
(conj stack (Long. item))))] ; if it wasn't an operator, we'll assume it's a long. Could choose bigint, or even read-line
|
||||
(reductions rpn-reducer [] (clojure.string/split string #"\s+")))) ;reductions is like reduce only shows all the intermediate steps
|
||||
|
||||
(let [stacks (rpn "3 4 2 * 1 5 - 2 3 ^ ^ / +")] ;bind it so we can output the answer separately.
|
||||
(println "stacks: ")
|
||||
(clojure.pprint/pprint stacks)
|
||||
(print "answer:" (->> stacks last first)))
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
import std.stdio, std.string, std.conv, std.typetuple;
|
||||
|
||||
void main() {
|
||||
auto input = "3 4 2 * 1 5 - 2 3 ^ ^ / +";
|
||||
writeln("For postfix expression: ", input);
|
||||
writeln("\nToken Action Stack");
|
||||
real[] stack;
|
||||
foreach (tok; input.split()) {
|
||||
auto action = "Apply op to top of stack";
|
||||
switch (tok) {
|
||||
foreach (o; TypeTuple!("+", "-", "*", "/", "^")) {
|
||||
case o:
|
||||
mixin("stack[$ - 2]" ~
|
||||
(o == "^" ? "^^" : o) ~ "=stack[$ - 1];");
|
||||
stack.length--;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
action = "Push num onto top of stack";
|
||||
stack ~= to!real(tok);
|
||||
}
|
||||
writefln("%3s %-26s %s", tok, action, stack);
|
||||
}
|
||||
writeln("\nThe final value is ", stack[0]);
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
open string console list format read
|
||||
|
||||
eval str = writen "Input\tOperation\tStack after" $
|
||||
eval' (split " " str) []
|
||||
where eval' [] (s::_) = printfn "Result: {0}" s
|
||||
eval' (x::xs) sta | "+"? = eval' xs <| op (+)
|
||||
| "-"? = eval' xs <| op (-)
|
||||
| "^"? = eval' xs <| op (**)
|
||||
| "/"? = eval' xs <| op (/)
|
||||
| "*"? = eval' xs <| op (*)
|
||||
| else = eval' xs <| conv x
|
||||
where c? = x == c
|
||||
op (^) = out "Operate" st' $ st'
|
||||
where st' = (head ss ^ s) :: tail ss
|
||||
conv x = out "Push" st' $ st'
|
||||
where st' = readStr x :: sta
|
||||
(s,ss) | sta == [] = ((),[])
|
||||
| else = (head sta,tail sta)
|
||||
out op st' = printfn "{0}\t{1}\t\t{2}" x op st'
|
||||
|
||||
eval "3 4 2 * 1 5 - 2 3 ^ ^ / +"
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var input = "3 4 2 * 1 5 - 2 3 ^ ^ / +"
|
||||
|
||||
func main() {
|
||||
fmt.Printf("For postfix %q\n", input)
|
||||
fmt.Println("\nToken Action Stack")
|
||||
var stack []float64
|
||||
for _, tok := range strings.Fields(input) {
|
||||
action := "Apply op to top of stack"
|
||||
switch tok {
|
||||
case "+":
|
||||
stack[len(stack)-2] += stack[len(stack)-1]
|
||||
stack = stack[:len(stack)-1]
|
||||
case "-":
|
||||
stack[len(stack)-2] -= stack[len(stack)-1]
|
||||
stack = stack[:len(stack)-1]
|
||||
case "*":
|
||||
stack[len(stack)-2] *= stack[len(stack)-1]
|
||||
stack = stack[:len(stack)-1]
|
||||
case "/":
|
||||
stack[len(stack)-2] /= stack[len(stack)-1]
|
||||
stack = stack[:len(stack)-1]
|
||||
case "^":
|
||||
stack[len(stack)-2] =
|
||||
math.Pow(stack[len(stack)-2], stack[len(stack)-1])
|
||||
stack = stack[:len(stack)-1]
|
||||
default:
|
||||
action = "Push num onto top of stack"
|
||||
f, _ := strconv.ParseFloat(tok, 64)
|
||||
stack = append(stack, f)
|
||||
}
|
||||
fmt.Printf("%3s %-26s %v\n", tok, action, stack)
|
||||
}
|
||||
fmt.Println("\nThe final value is", stack[0])
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
def evaluateRPN(expression) {
|
||||
def stack = [] as Stack
|
||||
def binaryOp = { action -> return { action.call(stack.pop(), stack.pop()) } }
|
||||
def actions = [
|
||||
'+': binaryOp { a, b -> b + a },
|
||||
'-': binaryOp { a, b -> b - a },
|
||||
'*': binaryOp { a, b -> b * a },
|
||||
'/': binaryOp { a, b -> b / a },
|
||||
'^': binaryOp { a, b -> b ** a }
|
||||
]
|
||||
expression.split(' ').each { item ->
|
||||
def action = actions[item] ?: { item as BigDecimal }
|
||||
stack.push(action.call())
|
||||
|
||||
println "$item: $stack"
|
||||
}
|
||||
assert stack.size() == 1 : "Unbalanced Expression: $expression ($stack)"
|
||||
stack.pop()
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
println evaluateRPN('3 4 2 * 1 5 - 2 3 ^ ^ / +')
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
import Data.List (elemIndex)
|
||||
|
||||
-- Show results
|
||||
main = mapM_ (\(x, y) -> putStrLn $ x ++ " ==> " ++ show y) $ reverse $ zip b (a:c)
|
||||
where (a, b, c) = solve "3 4 2 * 1 5 - 2 3 ^ ^ / +"
|
||||
|
||||
-- Solve and report RPN
|
||||
solve = foldl reduce ([], [], []) . words
|
||||
reduce (xs, ps, st) w =
|
||||
if i == Nothing
|
||||
then (read w:xs, ("Pushing " ++ w):ps, xs:st)
|
||||
else (([(*),(+),(-),(/),(**)]!!o) a b:zs, ("Performing " ++ w):ps, xs:st)
|
||||
where i = elemIndex (head w) "*+-/^"
|
||||
Just o = i
|
||||
(b:a:zs) = xs
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
procedure main()
|
||||
EvalRPN("3 4 2 * 1 5 - 2 3 ^ ^ / +")
|
||||
end
|
||||
|
||||
link printf
|
||||
invocable all
|
||||
|
||||
procedure EvalRPN(expr) #: evaluate (and trace stack) an RPN string
|
||||
|
||||
stack := []
|
||||
expr ? until pos(0) do {
|
||||
tab(many(' ')) # consume previous seperator
|
||||
token := tab(upto(' ')|0) # get token
|
||||
if token := numeric(token) then { # ... numeric
|
||||
push(stack,token)
|
||||
printf("pushed numeric %i : %s\n",token,list2string(stack))
|
||||
}
|
||||
else { # ... operator
|
||||
every b|a := pop(stack) # pop & reverse operands
|
||||
case token of {
|
||||
"+"|"-"|"*"|"^" : push(stack,token(a,b))
|
||||
"/" : push(stack,token(real(a),b))
|
||||
default : runerr(205,token)
|
||||
}
|
||||
printf("applied operator %s : %s\n",token,list2string(stack))
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
procedure list2string(L) #: format list as a string
|
||||
every (s := "[ ") ||:= !L || " "
|
||||
return s || "]"
|
||||
end
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
a: , <;._1 ' ' , '3 4 2 * 1 5 - 2 3 ^ ^ / +'
|
||||
┌┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┐
|
||||
││3│4│2│*│1│5│-│2│3│^│^│/│+│
|
||||
└┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┘
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
isOp=: '_+-*/^' e.~ {.@>@{.
|
||||
mo=: 1 :'(}: , u@{:) @ ['
|
||||
dy=: 1 :'(_2&}. , u/@(_2&{.)) @ ['
|
||||
dispatch=: (-mo)`(+dy)`(-dy)`(*dy)`(%dy)`(^dy)@.('_+-*/^' i. {.@>@])
|
||||
doShift=: (<@, ".@>@{.) , }.@]
|
||||
doApply=: }.@] ,~ [ <@dispatch {.@]
|
||||
consume=: [: ([ smoutput@>@{.) >@{. doShift`doApply@.(isOp@]) }.
|
||||
consume ^: (<:@#) a: , <;._1 ' ' , '3 4 2 * 1 5 - 2 3 ^ ^ / +'
|
||||
3
|
||||
3 4
|
||||
3 4 2
|
||||
3 8
|
||||
3 8 1
|
||||
3 8 1 5
|
||||
3 8 _4
|
||||
3 8 _4 2
|
||||
3 8 _4 2 3
|
||||
3 8 _4 8
|
||||
3 8 65536
|
||||
3 0.00012207
|
||||
3.00012
|
||||
┌───────┐
|
||||
│3.00012│
|
||||
└───────┘
|
||||
consume ^: (<:@#) a: , <;._1 ' ' , '3 _ 4 +'
|
||||
3
|
||||
_3
|
||||
_3 4
|
||||
1
|
||||
┌─┐
|
||||
│1│
|
||||
└─┘
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
import java.util.LinkedList;
|
||||
|
||||
public class RPN{
|
||||
public static void evalRPN(String expr){
|
||||
String cleanExpr = cleanExpr(expr);
|
||||
LinkedList<Double> stack = new LinkedList<Double>();
|
||||
System.out.println("Input\tOperation\tStack after");
|
||||
for(String token:cleanExpr.split("\\s")){
|
||||
System.out.print(token+"\t");
|
||||
Double tokenNum = null;
|
||||
try{
|
||||
tokenNum = Double.parseDouble(token);
|
||||
}catch(NumberFormatException e){}
|
||||
if(tokenNum != null){
|
||||
System.out.print("Push\t\t");
|
||||
stack.push(Double.parseDouble(token+""));
|
||||
}else if(token.equals("*")){
|
||||
System.out.print("Operate\t\t");
|
||||
double secondOperand = stack.pop();
|
||||
double firstOperand = stack.pop();
|
||||
stack.push(firstOperand * secondOperand);
|
||||
}else if(token.equals("/")){
|
||||
System.out.print("Operate\t\t");
|
||||
double secondOperand = stack.pop();
|
||||
double firstOperand = stack.pop();
|
||||
stack.push(firstOperand / secondOperand);
|
||||
}else if(token.equals("-")){
|
||||
System.out.print("Operate\t\t");
|
||||
double secondOperand = stack.pop();
|
||||
double firstOperand = stack.pop();
|
||||
stack.push(firstOperand - secondOperand);
|
||||
}else if(token.equals("+")){
|
||||
System.out.print("Operate\t\t");
|
||||
double secondOperand = stack.pop();
|
||||
double firstOperand = stack.pop();
|
||||
stack.push(firstOperand + secondOperand);
|
||||
}else if(token.equals("^")){
|
||||
System.out.print("Operate\t\t");
|
||||
double secondOperand = stack.pop();
|
||||
double firstOperand = stack.pop();
|
||||
stack.push(Math.pow(firstOperand, secondOperand));
|
||||
}else{//just in case
|
||||
System.out.println("Error");
|
||||
return;
|
||||
}
|
||||
System.out.println(stack);
|
||||
}
|
||||
System.out.println("Final answer: " + stack.pop());
|
||||
}
|
||||
|
||||
private static String cleanExpr(String expr){
|
||||
//remove all non-operators, non-whitespace, and non digit chars
|
||||
return expr.replaceAll("[^\\^\\*\\+\\-\\d/\\s]", "");
|
||||
}
|
||||
|
||||
public static void main(String[] args){
|
||||
evalRPN("3 4 2 * 1 5 - 2 3 ^ ^ / +");
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,88 @@
|
|||
/* NetRexx */
|
||||
options replace format comments java crossref symbols nobinary
|
||||
|
||||
numeric digits 20
|
||||
|
||||
rpnDefaultExpression = '3 4 2 * 1 5 - 2 3 ^ ^ / +'
|
||||
EODAD = '.*'
|
||||
|
||||
parse arg rpnString
|
||||
|
||||
if rpnString = '.' then rpnString = rpnDefaultExpression
|
||||
if rpnString = '' then do
|
||||
say 'Enter numbers or operators [to stop enter' EODAD']:'
|
||||
loop label rpnloop forever
|
||||
rpnval = ask
|
||||
if rpnval == EODAD then leave rpnloop
|
||||
rpnString = rpnString rpnval
|
||||
end rpnloop
|
||||
end
|
||||
|
||||
rpnString = rpnString.space(1)
|
||||
say rpnString':' evaluateRPN(rpnString)
|
||||
|
||||
return
|
||||
|
||||
-- -----------------------------------------------------------------------------
|
||||
method evaluateRPN(rpnString) public static returns Rexx
|
||||
|
||||
stack = LinkedList()
|
||||
op = 0
|
||||
L = 'L'
|
||||
R = 'R'
|
||||
rpnString = rpnString.strip('b')
|
||||
say 'Input\tOperation\tStack after'
|
||||
loop label rpn while rpnString.length > 0
|
||||
parse rpnString token rest
|
||||
rpnString = rest.strip('b')
|
||||
say token || '\t\-'
|
||||
select label tox case token
|
||||
when '*' then do
|
||||
say 'Operate\t\t\-'
|
||||
op[R] = Rexx stack.pop()
|
||||
op[L] = Rexx stack.pop()
|
||||
stack.push(op[L] * op[R])
|
||||
end
|
||||
when '/' then do
|
||||
say 'Operate\t\t\-'
|
||||
op[R] = Rexx stack.pop()
|
||||
op[L] = Rexx stack.pop()
|
||||
stack.push(op[L] / op[R])
|
||||
end
|
||||
when '+' then do
|
||||
say 'Operate\t\t\-'
|
||||
op[R] = Rexx stack.pop()
|
||||
op[L] = Rexx stack.pop()
|
||||
stack.push(op[L] + op[R])
|
||||
end
|
||||
when '-' then do
|
||||
say 'Operate\t\t\-'
|
||||
op[R] = Rexx stack.pop()
|
||||
op[L] = Rexx stack.pop()
|
||||
stack.push(op[L] - op[R])
|
||||
end
|
||||
when '^' then do
|
||||
say 'Operate\t\t\-'
|
||||
op[R] = Rexx stack.pop()
|
||||
op[L] = Rexx stack.pop()
|
||||
-- If exponent is a whole number use Rexx built-in exponentiation operation, otherwise use Math.pow()
|
||||
op[R] = op[R] + 0
|
||||
if op[R].datatype('w') then stack.push(op[L] ** op[R])
|
||||
else stack.push(Rexx Math.pow(op[L], op[R]))
|
||||
end
|
||||
otherwise do
|
||||
if token.datatype('n') then do
|
||||
say 'Push\t\t\-'
|
||||
stack.push(token)
|
||||
end
|
||||
else do
|
||||
say 'Error\t\t\-'
|
||||
end
|
||||
end
|
||||
end tox
|
||||
calc = Rexx
|
||||
say stack.toString
|
||||
end rpn
|
||||
say
|
||||
calc = stack.toString
|
||||
return calc
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
use IO;
|
||||
use Struct;
|
||||
|
||||
bundle Default {
|
||||
class RpnCalc {
|
||||
function : Main(args : String[]) ~ Nil {
|
||||
Caculate("3 4 2 * 1 5 - 2 3 ^ ^ / +");
|
||||
}
|
||||
|
||||
function : native : Caculate(rpn : String) ~ Nil {
|
||||
rpn->PrintLine();
|
||||
|
||||
tokens := rpn->Split(" ");
|
||||
stack := FloatVector->New();
|
||||
each(i : tokens) {
|
||||
token := tokens[i]->Trim();
|
||||
if(token->Size() > 0) {
|
||||
if(token->Get(0)->IsDigit()) {
|
||||
stack->AddBack(token->ToFloat());
|
||||
}
|
||||
else {
|
||||
right := stack->Get(stack->Size() - 1); stack->RemoveBack();
|
||||
left := stack->Get(stack->Size() - 1); stack->RemoveBack();
|
||||
select(token->Get(0)) {
|
||||
label '+': {
|
||||
stack->AddBack(left + right);
|
||||
}
|
||||
|
||||
label '-': {
|
||||
stack->AddBack(left - right);
|
||||
}
|
||||
|
||||
label '*': {
|
||||
stack->AddBack(left * right);
|
||||
}
|
||||
|
||||
label '/': {
|
||||
stack->AddBack(left / right);
|
||||
}
|
||||
|
||||
label '^': {
|
||||
stack->AddBack(right->Power(left));
|
||||
}
|
||||
};
|
||||
};
|
||||
PrintStack(stack);
|
||||
};
|
||||
};
|
||||
Console->Print("result: ")->PrintLine(stack->Get(0));
|
||||
}
|
||||
|
||||
function : PrintStack(stack : FloatVector) ~ Nil {
|
||||
" ["->Print();
|
||||
each(i : stack) {
|
||||
stack->Get(i)->Print();
|
||||
if(i + 1< stack->Size()) {
|
||||
", "->Print();
|
||||
};
|
||||
};
|
||||
']'->PrintLine();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
<?php
|
||||
// RPN Calculator
|
||||
//
|
||||
// Nigel Galloway - April 3rd., 2012
|
||||
//
|
||||
$WSb = '(?:^|\s+)';
|
||||
$WSa = '(?:\s+|$)';
|
||||
$num = '([+-]?(?:\.\d+|\d+(?:\.\d*)?))';
|
||||
$op = '([-+*\/^])';
|
||||
|
||||
function myE($m) {
|
||||
return $m[3] == '^' ? ' ' . pow($m[1], $m[2]) . ' ' : ' ' . eval("return " . $m[1] . $m[3] . $m[2] . ";") . ' ';
|
||||
}
|
||||
|
||||
while (!feof(STDIN)) {
|
||||
$s = trim(fgets(STDIN));
|
||||
if ($s == '')
|
||||
continue;
|
||||
do {
|
||||
$s = preg_replace_callback("/$WSb$num\\s+$num\\s+$op$WSa/", "myE", $s, -1, $n);
|
||||
} while ($n);
|
||||
echo floatval($s) . "\n";
|
||||
}
|
||||
?>
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
Calculator: procedure options (main); /* 14 Sept. 2012 */
|
||||
declare expression character (100) varying initial ('');
|
||||
declare ch character (1);
|
||||
declare (stack controlled, operand) float (18);
|
||||
declare in file input;
|
||||
|
||||
open file (in) title ('/CALCULAT.DAT,type(text),recsize(100)');
|
||||
on endfile (in) go to done;
|
||||
|
||||
put ('Stack contents:');
|
||||
main_loop:
|
||||
do forever;
|
||||
get file (in) edit (ch) (a(1));
|
||||
expression = expression || ch;
|
||||
if ch = ' ' then iterate;
|
||||
select (ch);
|
||||
when ('0', '1', '2', '3', '4', '5', '6', '7', '8', '9')
|
||||
do; allocate stack; stack = ch; iterate main_loop; end;
|
||||
when ('+') do; operand = stack; free stack; stack = stack + operand; end;
|
||||
when ('-') do; operand = stack; free stack; stack = stack - operand; end;
|
||||
when ('*') do; operand = stack; free stack; stack = stack * operand; end;
|
||||
when ('/') do; operand = stack; free stack; stack = stack / operand; end;
|
||||
when ('^') do; operand = stack; free stack; stack = stack ** operand; end;
|
||||
end;
|
||||
call show_stack;
|
||||
end;
|
||||
|
||||
done:
|
||||
put skip list ('The reverse polish expression = ' || expression);
|
||||
put skip list ('The evaluated expression = ' || stack);
|
||||
|
||||
end Calculator;
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
my $proggie = '3 4 2 * 1 5 - 2 3 ^ ^ / +';
|
||||
|
||||
class RPN is Array {
|
||||
|
||||
method binop(&infix:<op>) { self.push: self.pop Rop self.pop }
|
||||
|
||||
method run($p) {
|
||||
for $p.words {
|
||||
say "$_ ({self})";
|
||||
when /\d/ { self.push: $_ }
|
||||
when '+' { self.binop: &[+] }
|
||||
when '-' { self.binop: &[-] }
|
||||
when '*' { self.binop: &[*] }
|
||||
when '/' { self.binop: &[/] }
|
||||
when '^' { self.binop: &[**] }
|
||||
default { die "$_ is bogus" }
|
||||
}
|
||||
say self;
|
||||
}
|
||||
}
|
||||
|
||||
RPN.new.run($proggie);
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
# RPN calculator
|
||||
#
|
||||
# Nigel Galloway April 2nd., 2012
|
||||
#
|
||||
$WSb = '(?:^|\s+)';
|
||||
$WSa = '(?:\s+|$)';
|
||||
$num = '([+-/]?(?:\.\d+|\d+(?:\.\d*)?))';
|
||||
$op = '([-+*/^])';
|
||||
sub myE {
|
||||
my $a = '('.$1.')'.$3.'('.$2.')';
|
||||
$a =~ s/\^/**/;
|
||||
return eval($a);
|
||||
}
|
||||
while (<>) {
|
||||
while (s/$WSb$num\s+$num\s+$op$WSa/' '.myE().' '/e) {}
|
||||
print ($_, "\n");
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
(de rpnCalculator (Str)
|
||||
(let (^ ** Stack) # Define '^' from the built-in '**'
|
||||
(prinl "Token Stack")
|
||||
(for Token (str Str "*+-/\^")
|
||||
(if (num? Token)
|
||||
(push 'Stack @)
|
||||
(set (cdr Stack)
|
||||
((intern Token) (cadr Stack) (pop 'Stack)) ) )
|
||||
(prin Token)
|
||||
(space 6)
|
||||
(println Stack) )
|
||||
(println (car Stack)) ) )
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
: (rpnCalculator "3 4 2 * 1 5 - 2 3 \^ \^ / +")
|
||||
Token Stack
|
||||
3 (3)
|
||||
4 (4 3)
|
||||
2 (2 4 3)
|
||||
* (8 3)
|
||||
1 (1 8 3)
|
||||
5 (5 1 8 3)
|
||||
- (-4 8 3)
|
||||
2 (2 -4 8 3)
|
||||
3 (3 2 -4 8 3)
|
||||
^ (8 -4 8 3)
|
||||
^ (65536 8 3)
|
||||
/ (0 3)
|
||||
+ (3)
|
||||
3
|
||||
-> 3
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
rpn(L) :-
|
||||
writeln('Token Action Stack'),
|
||||
parse(L, [],[X] ,[]),
|
||||
format('~nThe final output value is ~w~n', [X]).
|
||||
|
||||
% skip spaces
|
||||
parse([X|L], St) -->
|
||||
{char_type(X, white)},
|
||||
parse(L, St).
|
||||
|
||||
% detect operators
|
||||
parse([Op|L], [Y, X | St]) -->
|
||||
{ is_op(Op, X, Y, V),
|
||||
writef(' %s', [[Op]]),
|
||||
with_output_to(atom(Str2), writef('Apply %s on top of stack', [[Op]])),
|
||||
writef(' %35l', [Str2]),
|
||||
writef('%w\n', [[V | St]])},
|
||||
parse(L, [V | St]).
|
||||
|
||||
% detect number
|
||||
parse([N|L], St) -->
|
||||
{char_type(N, digit)},
|
||||
parse_number(L, [N], St).
|
||||
|
||||
% string is finished
|
||||
parse([], St) --> St.
|
||||
|
||||
% compute numbers
|
||||
parse_number([N|L], NC, St) -->
|
||||
{char_type(N, digit)},
|
||||
parse_number(L, [N|NC], St).
|
||||
|
||||
parse_number(S, NC, St) -->
|
||||
{ reverse(NC, RNC),
|
||||
number_chars(V, RNC),
|
||||
writef('%5r', [V]),
|
||||
with_output_to(atom(Str2), writef('Push num %w on top of stack', [V])),
|
||||
writef(' %35l', [Str2]),
|
||||
writef('%w\n', [[V | St]])},
|
||||
parse(S, [V|St]).
|
||||
|
||||
% defining operations
|
||||
is_op(42, X, Y, V) :- V is X*Y.
|
||||
is_op(43, X, Y, V) :- V is X+Y.
|
||||
is_op(45, X, Y, V) :- V is X-Y.
|
||||
is_op(47, X, Y, V) :- V is X/Y.
|
||||
is_op(94, X, Y, V) :- V is X**Y.
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
def op_pow(stack):
|
||||
b = stack.pop(); a = stack.pop()
|
||||
stack.append( a ** b )
|
||||
def op_mul(stack):
|
||||
b = stack.pop(); a = stack.pop()
|
||||
stack.append( a * b )
|
||||
def op_div(stack):
|
||||
b = stack.pop(); a = stack.pop()
|
||||
stack.append( a / b )
|
||||
def op_add(stack):
|
||||
b = stack.pop(); a = stack.pop()
|
||||
stack.append( a + b )
|
||||
def op_sub(stack):
|
||||
b = stack.pop(); a = stack.pop()
|
||||
stack.append( a - b )
|
||||
def op_num(stack, num):
|
||||
stack.append( num )
|
||||
|
||||
ops = {
|
||||
'^': op_pow,
|
||||
'*': op_mul,
|
||||
'/': op_div,
|
||||
'+': op_add,
|
||||
'-': op_sub,
|
||||
}
|
||||
|
||||
def get_input(inp = None):
|
||||
'Inputs an expression and returns list of tokens'
|
||||
|
||||
if inp is None:
|
||||
inp = input('expression: ')
|
||||
tokens = inp.strip().split()
|
||||
return tokens
|
||||
|
||||
def rpn_calc(tokens):
|
||||
stack = []
|
||||
table = ['TOKEN,ACTION,STACK'.split(',')]
|
||||
for token in tokens:
|
||||
if token in ops:
|
||||
action = 'Apply op to top of stack'
|
||||
ops[token](stack)
|
||||
table.append( (token, action, ' '.join(str(s) for s in stack)) )
|
||||
else:
|
||||
action = 'Push num onto top of stack'
|
||||
op_num(stack, eval(token))
|
||||
table.append( (token, action, ' '.join(str(s) for s in stack)) )
|
||||
return table
|
||||
|
||||
if __name__ == '__main__':
|
||||
rpn = '3 4 2 * 1 5 - 2 3 ^ ^ / +'
|
||||
print( 'For RPN expression: %r\n' % rpn )
|
||||
rp = rpn_calc(get_input(rpn))
|
||||
maxcolwidths = [max(len(y) for y in x) for x in zip(*rp)]
|
||||
row = rp[0]
|
||||
print( ' '.join('{cell:^{width}}'.format(width=width, cell=cell) for (width, cell) in zip(maxcolwidths, row)))
|
||||
for row in rp[1:]:
|
||||
print( ' '.join('{cell:<{width}}'.format(width=width, cell=cell) for (width, cell) in zip(maxcolwidths, row)))
|
||||
|
||||
print('\n The final output value is: %r' % rp[-1][2])
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
/* REXX ***************************************************************
|
||||
* 09.11.2012 Walter Pachl translates from PL/I
|
||||
**********************************************************************/
|
||||
fid='rpl.txt'
|
||||
ex=linein(fid)
|
||||
Say 'Input:' ex
|
||||
/* ex=' 3 4 2 * 1 5 - 2 3 ^ ^ / +' */
|
||||
Numeric Digits 15
|
||||
expr=''
|
||||
st.=0
|
||||
Say 'Stack contents:'
|
||||
do While ex<>''
|
||||
Parse Var ex ch +1 ex
|
||||
expr=expr||ch;
|
||||
if ch<>' ' then do
|
||||
select
|
||||
When pos(ch,'0123456789')>0 Then Do
|
||||
Call stack ch
|
||||
Iterate
|
||||
End
|
||||
when ch='+' Then do; operand=getstack(); st.sti = st.sti + operand; end;
|
||||
when ch='-' Then do; operand=getstack(); st.sti = st.sti - operand; end;
|
||||
when ch='*' Then do; operand=getstack(); st.sti = st.sti * operand; end;
|
||||
when ch='/' Then do; operand=getstack(); st.sti = st.sti / operand; end;
|
||||
when ch='^' Then do; operand=getstack(); st.sti = st.sti ** operand; end;
|
||||
end;
|
||||
call show_stack
|
||||
end
|
||||
end
|
||||
Say 'The reverse polish expression = 'expr
|
||||
Say 'The evaluated expression = 'st.1
|
||||
Exit
|
||||
stack: Procedure Expose st.
|
||||
/* put the argument on top of the stack */
|
||||
z=st.0+1
|
||||
st.z=arg(1)
|
||||
st.0=z
|
||||
Return
|
||||
getstack: Procedure Expose st. sti
|
||||
/* remove and return the stack's top element */
|
||||
z=st.0
|
||||
stk=st.z
|
||||
st.0=st.0-1
|
||||
sti=st.0
|
||||
Return stk
|
||||
show_stack: procedure Expose st.
|
||||
/* show the stack's contents */
|
||||
ol=''
|
||||
do i=1 To st.0
|
||||
ol=ol format(st.i,5,10)
|
||||
End
|
||||
Say ol
|
||||
Return
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
/*REXX program evaluates a Reverse Polish notation (RPN) expression.*/
|
||||
parse arg x; if x='' then x = '3 4 2 * 1 5 - 2 3 ^ ^ / +'; ox=x
|
||||
showSteps=1 /*set to 0 (zero) if working steps not wanted.*/
|
||||
x=space(x); tokens=words(x)
|
||||
do i=1 for tokens; @.i=word(x,i); end /*i*/ /*assign input tokens*/
|
||||
L=max(20,length(x)) /*use 20 for the min show width. */
|
||||
numeric digits L /*ensure enough digits for answer*/
|
||||
say center('operand',L,'─') center('stack',L*2,'─'); e='***error!***'
|
||||
op='- + / * ^'; add2s='add to───►stack'; z=; stack=
|
||||
|
||||
do #=1 for tokens; ?=@.#; ??=? /*process each token from @. list*/
|
||||
w=words(stack) /*stack count (# entries).*/
|
||||
if datatype(?,'N') then do; stack=stack ?; call show add2s; iterate; end
|
||||
if ?=='^' then ??="**" /*REXXify ^ ──► ** (make legal)*/
|
||||
interpret 'y=' word(stack,w-1) ?? word(stack,w) /*compute.*/
|
||||
if datatype(y,'W') then y=y/1 /*normalize the number with ÷ */
|
||||
_=subword(stack,1,w-2); stack=_ y /*rebuild the stack with answer. */
|
||||
call show ?
|
||||
end /*#*/
|
||||
|
||||
z=space(z stack) /*append any residual entries. */
|
||||
say; say ' RPN input:' ox; say ' answer──►' z /*show input & ans.*/
|
||||
parse source upper . y . /*invoked via C.L. or REXX pgm?*/
|
||||
if y=='COMMAND' | \datatype(z,'W') then exit /*stick a fork in it, done.*/
|
||||
else return z /*RESULT ──► invoker.*/
|
||||
/*──────────────────────────────────SHOW subroutine─────────────────────*/
|
||||
show: if showSteps then say center(arg(1),L) left(space(stack),L); return
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
/*REXX program evaluates a Reverse Polish notation (RPN) expression.*/
|
||||
parse arg x; if x='' then x = '3 4 2 * 1 5 - 2 3 ^ ^ / +'; ox=x
|
||||
showSteps=1 /*set to 0 (zero) if working steps not wanted.*/
|
||||
x=space(x); tokens=words(x) /*elide extra blanks;count tokens*/
|
||||
do i=1 for tokens; @.i=word(x,i); end /*i*/ /*assign input tokens*/
|
||||
L=max(20,length(x)) /*use 20 for the min show width. */
|
||||
numeric digits L /*ensure enough digits for answer*/
|
||||
say center('operand',L,'─') center('stack',L*2,'─'); e='***error!***'
|
||||
add2s='add to───►stack'; z=; stack=
|
||||
dop='/ // % ÷'; bop='& | &&' /*division ops; binary operands*/
|
||||
aop='- + * ^ **' dop bop; lop=aop '||' /*arithmetic ops; legal operands*/
|
||||
|
||||
do #=1 for tokens; ?=@.#; ??=? /*process each token from @. list*/
|
||||
w=words(stack); b=word(stack,max(1,w)) /*stack count; last entry.*/
|
||||
a=word(stack,max(1,w-1)) /*stack's "first" operand.*/
|
||||
division =wordpos(?,dop)\==0 /*flag: doing a division.*/
|
||||
arith =wordpos(?,aop)\==0 /*flag: doing arithmetic.*/
|
||||
bitOp =wordpos(?,bop)\==0 /*flag: doing binary math*/
|
||||
if datatype(?,'N') then do; stack=stack ?; call show add2s; iterate; end
|
||||
if wordpos(?,lop)==0 then do; z=e 'illegal operator:' ?; leave; end
|
||||
if w<2 then do; z=e 'illegal RPN expression.'; leave; end
|
||||
if ?=='^' then ??="**" /*REXXify ^ ──► ** (make legal)*/
|
||||
if ?=='÷' then ??="/" /*REXXify ÷ ──► / (make legal)*/
|
||||
if division & b=0 then do; z=e 'division by zero: ' b; leave; end
|
||||
if bitOp & \isBit(a) then do; z=e "token isn't logical: " a; leave; end
|
||||
if bitOp & \isBit(b) then do; z=e "token isn't logical: " b; leave; end
|
||||
interpret 'y=' a ?? b /*compute with two stack operands*/
|
||||
if datatype(y,'W') then y=y/1 /*normalize number with ÷ by 1.*/
|
||||
_=subword(stack,1,w-2); stack=_ y /*rebuild the stack with answer. */
|
||||
call show ?
|
||||
end /*#*/
|
||||
|
||||
if word(z,1)==e then stack= /*handle special case of errors. */
|
||||
z=space(z stack) /*append any residual entries. */
|
||||
say; say ' RPN input:' ox; say ' answer──►' z /*show input & ans.*/
|
||||
parse source upper . how . /*invoked via C.L. or REXX pgm?*/
|
||||
if how=='COMMAND' | ,
|
||||
\datatype(z,'W') then exit /*stick a fork in it, we're done.*/
|
||||
return z /*return Z ──► invoker (RESULT).*/
|
||||
/*──────────────────────────────────subroutines─────────────────────────*/
|
||||
isBit: return arg(1)==0 | arg(1)==1 /*returns 1 if arg1 is bin bit.*/
|
||||
show: if showSteps then say center(arg(1),L) left(space(stack),L); return
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
rpn = RPNExpression("3 4 2 * 1 5 - 2 3 ^ ^ / +")
|
||||
value = rpn.eval
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
prn$ = "3 4 2 * 1 5 - 2 3 ^ ^ / + "
|
||||
|
||||
j = 0
|
||||
while word$(prn$,i + 1," ") <> ""
|
||||
i = i + 1
|
||||
n$ = word$(prn$,i," ")
|
||||
if n$ < "0" or n$ > "9" then
|
||||
num1 = val(word$(stack$,s," "))
|
||||
num2 = val(word$(stack$,s-1," "))
|
||||
n = op(n$,num2,num1)
|
||||
s = s - 1
|
||||
stack$ = stk$(stack$,s -1,str$(n))
|
||||
print "Push Opr ";n$;" to stack: ";stack$
|
||||
else
|
||||
s = s + 1
|
||||
stack$ = stack$ + n$ + " "
|
||||
print "Push Num ";n$;" to stack: ";stack$
|
||||
end if
|
||||
wend
|
||||
|
||||
function stk$(stack$,s,a$)
|
||||
for i = 1 to s
|
||||
stk$ = stk$ + word$(stack$,i," ") + " "
|
||||
next i
|
||||
stk$ = stk$ + a$ + " "
|
||||
end function
|
||||
|
||||
FUNCTION op(op$,a,b)
|
||||
if op$ = "*" then op = a * b
|
||||
if op$ = "/" then op = a / b
|
||||
if op$ = "^" then op = a ^ b
|
||||
if op$ = "+" then op = a + b
|
||||
if op$ = "-" then op = a - b
|
||||
end function
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
# Helper
|
||||
proc pop stk {
|
||||
upvar 1 $stk s
|
||||
set val [lindex $s end]
|
||||
set s [lreplace $s end end]
|
||||
return $val
|
||||
}
|
||||
|
||||
proc evaluate rpn {
|
||||
set stack {}
|
||||
foreach token $rpn {
|
||||
set act "apply"
|
||||
switch $token {
|
||||
"^" {
|
||||
# Non-commutative operation
|
||||
set a [pop stack]
|
||||
lappend stack [expr {[pop stack] ** $a}]
|
||||
}
|
||||
"/" {
|
||||
# Non-commutative, special float handling
|
||||
set a [pop stack]
|
||||
set b [expr {[pop stack] / double($a)}]
|
||||
if {$b == round($b)} {set b [expr {round($b)}]}
|
||||
lappend stack $b
|
||||
}
|
||||
"*" {
|
||||
# Commutative operation
|
||||
lappend stack [expr {[pop stack] * [pop stack]}]
|
||||
}
|
||||
"-" {
|
||||
# Non-commutative operation
|
||||
set a [pop stack]
|
||||
lappend stack [expr {[pop stack] - $a}]
|
||||
}
|
||||
"+" {
|
||||
# Commutative operation
|
||||
lappend stack [expr {[pop stack] + [pop stack]}]
|
||||
}
|
||||
default {
|
||||
set act "push"
|
||||
lappend stack $token
|
||||
}
|
||||
}
|
||||
puts "$token\t$act\t$stack"
|
||||
}
|
||||
return [lindex $stack end]
|
||||
}
|
||||
|
||||
puts [evaluate {3 4 2 * 1 5 - 2 3 ^ ^ / +}]
|
||||
Loading…
Add table
Add a link
Reference in a new issue