tasks a-s

This commit is contained in:
Ingy döt Net 2013-04-10 23:57:08 -07:00
parent 47bf37c096
commit b83f433714
12433 changed files with 156208 additions and 123 deletions

View 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]].

View file

@ -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';

View file

@ -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;

View file

@ -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)
}

View file

@ -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%)

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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)))

View file

@ -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]);
}

View file

@ -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 ^ ^ / +"

View file

@ -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])
}

View file

@ -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()
}

View file

@ -0,0 +1 @@
println evaluateRPN('3 4 2 * 1 5 - 2 3 ^ ^ / +')

View file

@ -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

View file

@ -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

View file

@ -0,0 +1,4 @@
a: , <;._1 ' ' , '3 4 2 * 1 5 - 2 3 ^ ^ / +'
┌┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┐
││3│4│2│*│1│5│-│2│3│^│^│/│+│
└┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┘

View file

@ -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│
└─┘

View file

@ -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 ^ ^ / +");
}
}

View file

@ -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

View file

@ -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();
}
}
}

View file

@ -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";
}
?>

View file

@ -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;

View file

@ -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);

View file

@ -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");
}

View file

@ -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)) ) )

View file

@ -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

View file

@ -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.

View file

@ -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])

View file

@ -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

View file

@ -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 tostack'; 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

View file

@ -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 tostack'; 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

View file

@ -0,0 +1,2 @@
rpn = RPNExpression("3 4 2 * 1 5 - 2 3 ^ ^ / +")
value = rpn.eval

View file

@ -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

View file

@ -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 ^ ^ / +}]