Add all the A tasks
This commit is contained in:
parent
2dd7375f96
commit
051504d65b
1608 changed files with 18584 additions and 0 deletions
20
Task/Arithmetic-evaluation/0DESCRIPTION
Normal file
20
Task/Arithmetic-evaluation/0DESCRIPTION
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
Create a program which parses and evaluates arithmetic expressions.
|
||||
|
||||
;Requirements:
|
||||
* An [[wp:Abstract_syntax_tree|abstract-syntax tree]] (AST) for the expression must be created from parsing the input.
|
||||
* The AST must be used in evaluation, also, so the input may not be directly evaluated (e.g. by calling eval or a similar language feature.)
|
||||
* The expression will be a string or list of symbols like "(1+3)*7".
|
||||
* The four symbols + - * / must be supported as binary operators with conventional precedence rules.
|
||||
* Precedence-control parentheses must also be supported.
|
||||
|
||||
;Note:
|
||||
For those who don't remember, mathematical precedence is as follows:
|
||||
* Parentheses
|
||||
* Multiplication/Division (left to right)
|
||||
* Addition/Subtraction (left to right)
|
||||
|
||||
|
||||
;C.f:
|
||||
* [[24 game Player]].
|
||||
* [[Parsing/RPN calculator algorithm]].
|
||||
* [[Parsing/RPN to infix conversion]].
|
||||
3
Task/Arithmetic-evaluation/1META.yaml
Normal file
3
Task/Arithmetic-evaluation/1META.yaml
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
---
|
||||
category:
|
||||
- Recursion
|
||||
142
Task/Arithmetic-evaluation/ALGOL-68/arithmetic-evaluation.alg
Normal file
142
Task/Arithmetic-evaluation/ALGOL-68/arithmetic-evaluation.alg
Normal file
|
|
@ -0,0 +1,142 @@
|
|||
INT base=10;
|
||||
MODE FIXED = LONG REAL; # numbers in the format 9,999.999 #
|
||||
|
||||
#IF build abstract syntax tree and then EVAL tree #
|
||||
MODE AST = UNION(NODE, FIXED);
|
||||
MODE NUM = REF AST;
|
||||
MODE NODE = STRUCT(NUM a, PROC (FIXED,FIXED)FIXED op, NUM b);
|
||||
|
||||
OP EVAL = (NUM ast)FIXED:(
|
||||
CASE ast IN
|
||||
(FIXED num): num,
|
||||
(NODE fork): (op OF fork)(EVAL( a OF fork), EVAL (b OF fork))
|
||||
ESAC
|
||||
);
|
||||
|
||||
OP + = (NUM a,b)NUM: ( HEAP AST := NODE(a, (FIXED a,b)FIXED:a+b, b) );
|
||||
OP - = (NUM a,b)NUM: ( HEAP AST := NODE(a, (FIXED a,b)FIXED:a-b, b) );
|
||||
OP * = (NUM a,b)NUM: ( HEAP AST := NODE(a, (FIXED a,b)FIXED:a*b, b) );
|
||||
OP / = (NUM a,b)NUM: ( HEAP AST := NODE(a, (FIXED a,b)FIXED:a/b, b) );
|
||||
OP **= (NUM a,b)NUM: ( HEAP AST := NODE(a, (FIXED a,b)FIXED:a**b, b) );
|
||||
|
||||
#ELSE simply use REAL arithmetic with no abstract syntax tree at all # CO
|
||||
MODE NUM = FIXED, AST = FIXED;
|
||||
OP EVAL = (FIXED num)FIXED: num;
|
||||
#FI# END CO
|
||||
|
||||
MODE LEX = PROC (TOK)NUM;
|
||||
MODE MONADIC =PROC (NUM)NUM;
|
||||
MODE DIADIC = PROC (NUM,NUM)NUM;
|
||||
|
||||
MODE TOK = CHAR;
|
||||
MODE ACTION = UNION(STACKACTION, LEX, MONADIC, DIADIC);
|
||||
MODE OPVAL = STRUCT(INT prio, ACTION action);
|
||||
MODE OPITEM = STRUCT(TOK token, OPVAL opval);
|
||||
|
||||
[256]STACKITEM stack;
|
||||
MODE STACKITEM = STRUCT(NUM value, OPVAL op);
|
||||
MODE STACKACTION = PROC (REF STACKITEM)VOID;
|
||||
|
||||
PROC begin = (REF STACKITEM top)VOID: prio OF op OF top -:= +10;
|
||||
PROC end = (REF STACKITEM top)VOID: prio OF op OF top -:= -10;
|
||||
|
||||
OP ** = (COMPL a,b)COMPL: complex exp(complex ln(a)*b);
|
||||
|
||||
[8]OPITEM op list :=(
|
||||
# OP PRIO ACTION #
|
||||
("^", (8, (NUM a,b)NUM: a**b)),
|
||||
("*", (7, (NUM a,b)NUM: a*b)),
|
||||
("/", (7, (NUM a,b)NUM: a/b)),
|
||||
("+", (6, (NUM a,b)NUM: a+b)),
|
||||
("-", (6, (NUM a,b)NUM: a-b)),
|
||||
("(",(+10, begin)),
|
||||
(")",(-10, end)),
|
||||
("?", (9, LEX:SKIP))
|
||||
);
|
||||
|
||||
PROC op dict = (TOK op)REF OPVAL:(
|
||||
# This can be unrolled to increase performance #
|
||||
REF OPITEM candidate;
|
||||
FOR i TO UPB op list WHILE
|
||||
candidate := op list[i];
|
||||
# WHILE # op /= token OF candidate DO
|
||||
SKIP
|
||||
OD;
|
||||
opval OF candidate
|
||||
);
|
||||
|
||||
PROC build ast = (STRING expr)NUM:(
|
||||
|
||||
INT top:=0;
|
||||
|
||||
PROC compress ast stack = (INT prio, NUM in value)NUM:(
|
||||
NUM out value := in value;
|
||||
FOR loc FROM top BY -1 TO 1 WHILE
|
||||
REF STACKITEM stack top := stack[loc];
|
||||
# WHILE # ( top >= LWB stack | prio <= prio OF op OF stack top | FALSE ) DO
|
||||
top := loc - 1;
|
||||
out value :=
|
||||
CASE action OF op OF stack top IN
|
||||
(MONADIC op): op(value OF stack top), # not implemented #
|
||||
(DIADIC op): op(value OF stack top,out value)
|
||||
ESAC
|
||||
OD;
|
||||
out value
|
||||
);
|
||||
|
||||
NUM value := NIL;
|
||||
FIXED num value;
|
||||
INT decimal places;
|
||||
|
||||
FOR i TO UPB expr DO
|
||||
TOK token = expr[i];
|
||||
REF OPVAL this op := op dict(token);
|
||||
CASE action OF this op IN
|
||||
(STACKACTION action):(
|
||||
IF prio OF thisop = -10 THEN
|
||||
value := compress ast stack(0, value)
|
||||
FI;
|
||||
IF top >= LWB stack THEN
|
||||
action(stack[top])
|
||||
FI
|
||||
),
|
||||
(LEX):( # a crude lexer #
|
||||
SHORT INT digit = ABS token - ABS "0";
|
||||
IF 0<= digit AND digit < base THEN
|
||||
IF NUM(value) IS NIL THEN # first digit #
|
||||
decimal places := 0;
|
||||
value := HEAP AST := num value := digit
|
||||
ELSE
|
||||
NUM(value) := num value := IF decimal places = 0
|
||||
THEN
|
||||
num value * base + digit
|
||||
ELSE
|
||||
decimal places *:= base;
|
||||
num value + digit / decimal places
|
||||
FI
|
||||
FI
|
||||
ELIF token = "." THEN
|
||||
decimal places := 1
|
||||
ELSE
|
||||
SKIP # and ignore spaces and any unrecognised characters #
|
||||
FI
|
||||
),
|
||||
(MONADIC): SKIP, # not implemented #
|
||||
(DIADIC):(
|
||||
value := compress ast stack(prio OF this op, value);
|
||||
IF top=UPB stack THEN index error FI;
|
||||
stack[top+:=1]:=STACKITEM(value, this op);
|
||||
value:=NIL
|
||||
)
|
||||
ESAC
|
||||
OD;
|
||||
compress ast stack(-max int, value)
|
||||
);
|
||||
|
||||
test:(
|
||||
printf(($" euler's number is about: "g(-long real width,long real width-2)l$,
|
||||
EVAL build ast("1+1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+1/15)/14)/13)/12)/11)/10)/9)/8)/7)/6)/5)/4)/3)/2")));
|
||||
SKIP EXIT
|
||||
index error:
|
||||
printf(("Stack over flow"))
|
||||
)
|
||||
|
|
@ -0,0 +1,150 @@
|
|||
/*
|
||||
hand coded recursive descent parser
|
||||
expr : term ( ( PLUS | MINUS ) term )* ;
|
||||
term : factor ( ( MULT | DIV ) factor )* ;
|
||||
factor : NUMBER | '(' expr ')';
|
||||
*/
|
||||
|
||||
calcLexer := makeCalcLexer()
|
||||
string := "((3+4)*(7*9)+3)+4"
|
||||
tokens := tokenize(string, calcLexer)
|
||||
msgbox % printTokens(tokens)
|
||||
ast := expr()
|
||||
msgbox % printTree(ast)
|
||||
msgbox % expression := evalTree(ast)
|
||||
filedelete expression.ahk
|
||||
fileappend, % "msgbox % " expression, expression.ahk
|
||||
run, expression.ahk
|
||||
return
|
||||
|
||||
|
||||
expr()
|
||||
{
|
||||
global tokens
|
||||
ast := object(1, "expr")
|
||||
if node := term()
|
||||
ast._Insert(node)
|
||||
loop
|
||||
{
|
||||
if peek("PLUS") or peek("MINUS")
|
||||
{
|
||||
op := getsym()
|
||||
newop := object(1, op.type, 2, op.value)
|
||||
node := term()
|
||||
ast._Insert(newop)
|
||||
ast._Insert(node)
|
||||
}
|
||||
Else
|
||||
Break
|
||||
}
|
||||
return ast
|
||||
}
|
||||
|
||||
term()
|
||||
{
|
||||
global tokens
|
||||
tree := object(1, "term")
|
||||
if node := factor()
|
||||
tree._Insert(node)
|
||||
loop
|
||||
{
|
||||
if peek("MULT") or peek("DIV")
|
||||
{
|
||||
op := getsym()
|
||||
newop := object(1, op.type, 2, op.value)
|
||||
node := factor()
|
||||
tree._Insert(newop)
|
||||
tree._Insert(node)
|
||||
}
|
||||
else
|
||||
Break
|
||||
}
|
||||
return tree
|
||||
}
|
||||
|
||||
factor()
|
||||
{
|
||||
global tokens
|
||||
if peek("NUMBER")
|
||||
{
|
||||
token := getsym()
|
||||
tree := object(1, token.type, 2, token.value)
|
||||
return tree
|
||||
}
|
||||
else if peek("OPEN")
|
||||
{
|
||||
getsym()
|
||||
tree := expr()
|
||||
if peek("CLOSE")
|
||||
{
|
||||
getsym()
|
||||
return tree
|
||||
}
|
||||
else
|
||||
error("miss closing parentheses ")
|
||||
}
|
||||
else
|
||||
error("no factor found")
|
||||
}
|
||||
|
||||
peek(type, n=1)
|
||||
{
|
||||
global tokens
|
||||
if (tokens[n, "type"] == type)
|
||||
return 1
|
||||
}
|
||||
|
||||
getsym(n=1)
|
||||
{
|
||||
global tokens
|
||||
return token := tokens._Remove(n)
|
||||
}
|
||||
|
||||
error(msg)
|
||||
{
|
||||
global tokens
|
||||
msgbox % msg " at:`n" printToken(tokens[1])
|
||||
}
|
||||
|
||||
|
||||
printTree(ast)
|
||||
{
|
||||
if !ast
|
||||
return
|
||||
|
||||
n := 0
|
||||
loop
|
||||
{
|
||||
n += 1
|
||||
if !node := ast[n]
|
||||
break
|
||||
if !isobject(node)
|
||||
treeString .= node
|
||||
else
|
||||
treeString .= printTree(node)
|
||||
}
|
||||
return ("(" treeString ")" )
|
||||
}
|
||||
|
||||
evalTree(ast)
|
||||
{
|
||||
if !ast
|
||||
return
|
||||
|
||||
n := 1
|
||||
loop
|
||||
{
|
||||
n += 1
|
||||
if !node := ast[n]
|
||||
break
|
||||
if !isobject(node)
|
||||
treeString .= node
|
||||
else
|
||||
treeString .= evalTree(node)
|
||||
}
|
||||
if (n == 3)
|
||||
return treeString
|
||||
return ("(" treeString ")" )
|
||||
}
|
||||
|
||||
#include calclex.ahk
|
||||
|
|
@ -0,0 +1,67 @@
|
|||
tokenize(string, lexer)
|
||||
{
|
||||
stringo := string ; store original string
|
||||
locationInString := 1
|
||||
size := strlen(string)
|
||||
tokens := object()
|
||||
|
||||
start:
|
||||
Enum := Lexer._NewEnum()
|
||||
While Enum[type, value] ; loop through regular expression lexing rules
|
||||
{
|
||||
if (1 == regexmatch(string, value, tokenValue))
|
||||
{
|
||||
token := object()
|
||||
token.pos := locationInString
|
||||
token.value := tokenValue
|
||||
token.length := strlen(tokenValue)
|
||||
token.type := type
|
||||
tokens._Insert(token)
|
||||
locationInString += token.length
|
||||
string := substr(string, token.length + 1)
|
||||
goto start
|
||||
}
|
||||
continue
|
||||
}
|
||||
if (locationInString < size)
|
||||
msgbox % "unrecognized token at " substr(stringo, locationInstring)
|
||||
return tokens
|
||||
}
|
||||
|
||||
makeCalcLexer()
|
||||
{
|
||||
calcLexer := object()
|
||||
PLUS := "\+"
|
||||
MINUS := "-"
|
||||
MULT := "\*"
|
||||
DIV := "/"
|
||||
OPEN := "\("
|
||||
CLOSE := "\)"
|
||||
NUMBER := "\d+"
|
||||
WS := "[ \t\n]+"
|
||||
END := "\."
|
||||
RULES := "PLUS,MINUS,MULT,DIV,OPEN,CLOSE,NUMBER,WS,END"
|
||||
loop, parse, rules, `,
|
||||
{
|
||||
type := A_LoopField
|
||||
value := %A_LoopField%
|
||||
calcLexer._Insert(type, value)
|
||||
}
|
||||
return calcLexer
|
||||
}
|
||||
|
||||
printTokens(tokens)
|
||||
{
|
||||
loop % tokens._MaxIndex()
|
||||
{
|
||||
tokenString .= printToken(tokens[A_Index]) "`n`n"
|
||||
}
|
||||
return tokenString
|
||||
}
|
||||
|
||||
|
||||
printToken(token)
|
||||
{
|
||||
string := "pos= " token.pos "`nvalue= " token.value "`ntype= " token.type
|
||||
return string
|
||||
}
|
||||
53
Task/Arithmetic-evaluation/Clojure/arithmetic-evaluation.clj
Normal file
53
Task/Arithmetic-evaluation/Clojure/arithmetic-evaluation.clj
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
(def precedence '{* 0, / 0
|
||||
+ 1, - 1})
|
||||
|
||||
(defn order-ops
|
||||
"((A x B) y C) or (A x (B y C)) depending on precedence of x and y"
|
||||
[[A x B y C & more]]
|
||||
(let [ret (if (<= (precedence x)
|
||||
(precedence y))
|
||||
(list (list A x B) y C)
|
||||
(list A x (list B y C)))]
|
||||
(if more
|
||||
(recur (concat ret more))
|
||||
ret)))
|
||||
|
||||
(defn add-parens
|
||||
"Tree walk to add parens. All lists are length 3 afterwards."
|
||||
[s]
|
||||
(clojure.walk/postwalk
|
||||
#(if (seq? %)
|
||||
(let [c (count %)]
|
||||
(cond (even? c) (throw (Exception. "Must be an odd number of forms"))
|
||||
(= c 1) (first %)
|
||||
(= c 3) %
|
||||
(>= c 5) (order-ops %)))
|
||||
%)
|
||||
s))
|
||||
|
||||
(defn make-ast
|
||||
"Parse a string into a list of numbers, ops, and lists"
|
||||
[s]
|
||||
(-> (format "'(%s)" s)
|
||||
(.replaceAll , "([*+-/])" " $1 ")
|
||||
load-string
|
||||
add-parens))
|
||||
|
||||
(def ops {'* *
|
||||
'+ +
|
||||
'- -
|
||||
'/ /})
|
||||
|
||||
(def eval-ast
|
||||
(partial clojure.walk/postwalk
|
||||
#(if (seq? %)
|
||||
(let [[a o b] %]
|
||||
((ops o) a b))
|
||||
%)))
|
||||
|
||||
(defn evaluate [s]
|
||||
"Parse and evaluate an infix arithmetic expression"
|
||||
(eval-ast (make-ast s)))
|
||||
|
||||
user> (evaluate "1 + 2*(3 - 2*(3 - 2)*((2 - 4)*5 - 22/(7 + 2*(3 - 1)) - 1)) + 1")
|
||||
60
|
||||
29
Task/Arithmetic-evaluation/Haskell/arithmetic-evaluation.hs
Normal file
29
Task/Arithmetic-evaluation/Haskell/arithmetic-evaluation.hs
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
import Text.ParserCombinators.Parsec
|
||||
import Text.ParserCombinators.Parsec.Expr
|
||||
|
||||
data Exp = Num Int
|
||||
| Add Exp Exp
|
||||
| Sub Exp Exp
|
||||
| Mul Exp Exp
|
||||
| Div Exp Exp
|
||||
|
||||
expr = buildExpressionParser table factor
|
||||
|
||||
table = [[op "*" (Mul) AssocLeft, op "/" (Div) AssocLeft]
|
||||
,[op "+" (Add) AssocLeft, op "-" (Sub) AssocLeft]]
|
||||
where op s f assoc = Infix (do string s; return f) assoc
|
||||
|
||||
factor = do char '(' ; x <- expr ; char ')'
|
||||
return x
|
||||
<|> do ds <- many1 digit
|
||||
return $ Num (read ds)
|
||||
|
||||
evaluate (Num x) = fromIntegral x
|
||||
evaluate (Add a b) = (evaluate a) + (evaluate b)
|
||||
evaluate (Sub a b) = (evaluate a) - (evaluate b)
|
||||
evaluate (Mul a b) = (evaluate a) * (evaluate b)
|
||||
evaluate (Div a b) = (evaluate a) `div` (evaluate b)
|
||||
|
||||
solution exp = case parse expr [] exp of
|
||||
Right expr -> evaluate expr
|
||||
Left _ -> error "Did not parse"
|
||||
138
Task/Arithmetic-evaluation/Java/arithmetic-evaluation.java
Normal file
138
Task/Arithmetic-evaluation/Java/arithmetic-evaluation.java
Normal file
|
|
@ -0,0 +1,138 @@
|
|||
import java.util.Stack;
|
||||
|
||||
public class ArithmeticEvaluation
|
||||
{
|
||||
public static enum Parentheses { LEFT, RIGHT }
|
||||
|
||||
public static enum BinaryOperator
|
||||
{
|
||||
ADD('+', 1) {
|
||||
public BigRational eval(BigRational leftValue, BigRational rightValue) { return leftValue.add(rightValue); }
|
||||
},
|
||||
SUB('-', 1) {
|
||||
public BigRational eval(BigRational leftValue, BigRational rightValue) { return leftValue.subtract(rightValue); }
|
||||
},
|
||||
MUL('*', 2) {
|
||||
public BigRational eval(BigRational leftValue, BigRational rightValue) { return leftValue.multiply(rightValue); }
|
||||
},
|
||||
DIV('/', 2) {
|
||||
public BigRational eval(BigRational leftValue, BigRational rightValue) { return leftValue.divide(rightValue); }
|
||||
};
|
||||
|
||||
public final char symbol;
|
||||
public final int precedence;
|
||||
|
||||
BinaryOperator(char symbol, int precedence)
|
||||
{
|
||||
this.symbol = symbol;
|
||||
this.precedence = precedence;
|
||||
}
|
||||
|
||||
public abstract BigRational eval(BigRational leftValue, BigRational rightValue);
|
||||
}
|
||||
|
||||
public static class BinaryExpression
|
||||
{
|
||||
public Object leftOperand = null;
|
||||
public BinaryOperator operator = null;
|
||||
public Object rightOperand = null;
|
||||
|
||||
public BinaryExpression(Object leftOperand, BinaryOperator operator, Object rightOperand)
|
||||
{
|
||||
this.leftOperand = leftOperand;
|
||||
this.operator = operator;
|
||||
this.rightOperand = rightOperand;
|
||||
}
|
||||
|
||||
public BigRational eval()
|
||||
{
|
||||
BigRational leftValue = (leftOperand instanceof BinaryExpression) ? ((BinaryExpression)leftOperand).eval() : (BigRational)leftOperand;
|
||||
BigRational rightValue = (rightOperand instanceof BinaryExpression) ? ((BinaryExpression)rightOperand).eval() : (BigRational)rightOperand;
|
||||
return operator.eval(leftValue, rightValue);
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{ return "(" + leftOperand + " " + operator.symbol + " " + rightOperand + ")"; }
|
||||
}
|
||||
|
||||
public static void createNewOperand(BinaryOperator operator, Stack<Object> operands)
|
||||
{
|
||||
Object rightOperand = operands.pop();
|
||||
operands.push(new BinaryExpression(operands.pop(), operator, rightOperand));
|
||||
return;
|
||||
}
|
||||
|
||||
public static Object createExpression(String inputString)
|
||||
{
|
||||
int curIndex = 0;
|
||||
boolean afterOperand = false;
|
||||
Stack<Object> operands = new Stack<Object>();
|
||||
Stack<Object> operators = new Stack<Object>();
|
||||
inputStringLoop:
|
||||
while (curIndex < inputString.length())
|
||||
{
|
||||
int startIndex = curIndex;
|
||||
char c = inputString.charAt(curIndex++);
|
||||
if (Character.isWhitespace(c))
|
||||
continue;
|
||||
if (afterOperand)
|
||||
{
|
||||
if (c == ')')
|
||||
{
|
||||
Object operator = null;
|
||||
while (!operators.isEmpty() && ((operator = operators.pop()) != Parentheses.LEFT))
|
||||
createNewOperand((BinaryOperator)operator, operands);
|
||||
continue;
|
||||
}
|
||||
afterOperand = false;
|
||||
for (BinaryOperator operator : BinaryOperator.values())
|
||||
{
|
||||
if (c == operator.symbol)
|
||||
{
|
||||
while (!operators.isEmpty() && (operators.peek() != Parentheses.LEFT) && (((BinaryOperator)operators.peek()).precedence >= operator.precedence))
|
||||
createNewOperand((BinaryOperator)operators.pop(), operands);
|
||||
operators.push(operator);
|
||||
continue inputStringLoop;
|
||||
}
|
||||
}
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
if (c == '(')
|
||||
{
|
||||
operators.push(Parentheses.LEFT);
|
||||
continue;
|
||||
}
|
||||
afterOperand = true;
|
||||
while (curIndex < inputString.length())
|
||||
{
|
||||
c = inputString.charAt(curIndex);
|
||||
if (((c < '0') || (c > '9')) && (c != '.'))
|
||||
break;
|
||||
curIndex++;
|
||||
}
|
||||
operands.push(BigRational.valueOf(inputString.substring(startIndex, curIndex)));
|
||||
}
|
||||
|
||||
while (!operators.isEmpty())
|
||||
{
|
||||
Object operator = operators.pop();
|
||||
if (operator == Parentheses.LEFT)
|
||||
throw new IllegalArgumentException();
|
||||
createNewOperand((BinaryOperator)operator, operands);
|
||||
}
|
||||
Object expression = operands.pop();
|
||||
if (!operands.isEmpty())
|
||||
throw new IllegalArgumentException();
|
||||
return expression;
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
String[] testExpressions = { "2+3", "2+3/4", "2*3-4", "2*(3+4)+5/6", "2 * (3 + (4 * 5 + (6 * 7) * 8) - 9) * 10", "2*-3--4+-.25" };
|
||||
for (String testExpression : testExpressions)
|
||||
{
|
||||
Object expression = createExpression(testExpression);
|
||||
System.out.println("Input: \"" + testExpression + "\", AST: \"" + expression + "\", eval=" + (expression instanceof BinaryExpression ? ((BinaryExpression)expression).eval() : expression));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
function evalArithmeticExp(s) {
|
||||
s = s.replace(/\s/g,'').replace(/^\+/,'');
|
||||
var rePara = /\([^\(\)]*\)/;
|
||||
var exp = s.match(rePara);
|
||||
|
||||
while (exp = s.match(rePara)) {
|
||||
s = s.replace(exp[0], evalExp(exp[0]));
|
||||
}
|
||||
return evalExp(s);
|
||||
|
||||
function evalExp(s) {
|
||||
s = s.replace(/[\(\)]/g,'');
|
||||
var reMD = /\d+\.?\d*\s*[\*\/]\s*[+-]?\d+\.?\d*/;
|
||||
var reM = /\*/;
|
||||
var reAS = /-?\d+\.?\d*\s*[\+-]\s*[+-]?\d+\.?\d*/;
|
||||
var reA = /\d\+/;
|
||||
var exp;
|
||||
|
||||
while (exp = s.match(reMD)) {
|
||||
s = exp[0].match(reM)? s.replace(exp[0], multiply(exp[0])) : s.replace(exp[0], divide(exp[0]));
|
||||
}
|
||||
|
||||
while (exp = s.match(reAS)) {
|
||||
s = exp[0].match(reA)? s.replace(exp[0], add(exp[0])) : s.replace(exp[0], subtract(exp[0]));
|
||||
}
|
||||
|
||||
return '' + s;
|
||||
|
||||
function multiply(s, b) {
|
||||
b = s.split('*');
|
||||
return b[0] * b[1];
|
||||
}
|
||||
|
||||
function divide(s, b) {
|
||||
b = s.split('/');
|
||||
return b[0] / b[1];
|
||||
}
|
||||
|
||||
function add(s, b) {
|
||||
s = s.replace(/^\+/,'').replace(/\++/,'+');
|
||||
b = s.split('+');
|
||||
return Number(b[0]) + Number(b[1]);
|
||||
}
|
||||
|
||||
function subtract(s, b) {
|
||||
s = s.replace(/\+-|-\+/g,'-');
|
||||
|
||||
if (s.match(/--/)) {
|
||||
return add(s.replace(/--/,'+'));
|
||||
}
|
||||
b = s.split('-');
|
||||
return b.length == 3? -1 * b[1] - b[2] : b[0] - b[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
40
Task/Arithmetic-evaluation/Lua/arithmetic-evaluation.lua
Normal file
40
Task/Arithmetic-evaluation/Lua/arithmetic-evaluation.lua
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
require"lpeg"
|
||||
|
||||
P, R, C, S, V = lpeg.P, lpeg.R, lpeg.C, lpeg.S, lpeg.V
|
||||
|
||||
--matches arithmetic expressions and returns a syntax tree
|
||||
expression = P{"expr";
|
||||
ws = P" "^0,
|
||||
number = C(R"09"^1) * V"ws",
|
||||
lp = "(" * V"ws",
|
||||
rp = ")" * V"ws",
|
||||
sym = C(S"+-*/") * V"ws",
|
||||
more = (V"sym" * V"expr")^0,
|
||||
expr = V"number" * V"more" + V"lp" * lpeg.Ct(V"expr" * V"more") * V"rp" * V"more"}
|
||||
|
||||
--evaluates a tree
|
||||
function eval(expr)
|
||||
--empty
|
||||
if type(expr) == "string" or type(expr) == "number" then return expr + 0 end
|
||||
|
||||
--arithmetic functions
|
||||
tb = {["+"] = function(a,b) return eval(a) + eval(b) end,
|
||||
["-"] = function(a,b) return eval(a) - eval(b) end,
|
||||
["*"] = function(a,b) return eval(a) * eval(b) end,
|
||||
["/"] = function(a,b) return eval(a) / eval(b) end}
|
||||
|
||||
--you could add ^ or other operators to this pretty easily
|
||||
for i, v in ipairs{"*/", "+-"} do
|
||||
for s, u in ipairs(expr) do
|
||||
local k = type(u) == "string" and C(S(v)):match(u)
|
||||
if k then
|
||||
expr[s-1] = tb[k](expr[s-1],expr[s+1])
|
||||
table.remove(expr, s)
|
||||
table.remove(expr, s)
|
||||
end
|
||||
end
|
||||
end
|
||||
return expr[1]
|
||||
end
|
||||
|
||||
print(eval{expression:match(io.read())})
|
||||
61
Task/Arithmetic-evaluation/Perl/arithmetic-evaluation.pl
Normal file
61
Task/Arithmetic-evaluation/Perl/arithmetic-evaluation.pl
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
sub ev
|
||||
# Evaluates an arithmetic expression like "(1+3)*7" and returns
|
||||
# its value.
|
||||
{my $exp = shift;
|
||||
# Delete all meaningless characters. (Scientific notation,
|
||||
# infinity, and not-a-number aren't supported.)
|
||||
$exp =~ tr {0-9.+-/*()} {}cd;
|
||||
return ev_ast(astize($exp));}
|
||||
|
||||
{my $balanced_paren_regex;
|
||||
$balanced_paren_regex = qr
|
||||
{\( ( [^()]+ | (??{$balanced_paren_regex}) )+ \)}x;
|
||||
# ??{ ... } interpolates lazily (only when necessary),
|
||||
# permitting recursion to arbitrary depths.
|
||||
|
||||
sub astize
|
||||
# Constructs an abstract syntax tree by recursively
|
||||
# transforming textual arithmetic expressions into array
|
||||
# references of the form [operator, left oprand, right oprand].
|
||||
{my $exp = shift;
|
||||
# If $exp is just a number, return it as-is.
|
||||
$exp =~ /[^0-9.]/ or return $exp;
|
||||
# If parentheses surround the entire expression, get rid of
|
||||
# them.
|
||||
$exp = substr($exp, 1, -1)
|
||||
while $exp =~ /\A($balanced_paren_regex)\z/;
|
||||
# Replace stuff in parentheses with placeholders.
|
||||
my @paren_contents;
|
||||
$exp =~ s {($balanced_paren_regex)}
|
||||
{push(@paren_contents, $1);
|
||||
"[p$#paren_contents]"}eg;
|
||||
# Scan for operators in order of increasing precedence,
|
||||
# preferring the rightmost.
|
||||
$exp =~ m{(.+) ([+-]) (.+)}x or
|
||||
$exp =~ m{(.+) ([*/]) (.+)}x or
|
||||
# The expression must've been malformed somehow.
|
||||
# (Note that unary minus isn't supported.)
|
||||
die "Eh?: [$exp]\n";
|
||||
my ($op, $lo, $ro) = ($2, $1, $3);
|
||||
# Restore the parenthetical expressions.
|
||||
s {\[p(\d+)\]} {($paren_contents[$1])}eg
|
||||
foreach $lo, $ro;
|
||||
# And recurse.
|
||||
return [$op, astize($lo), astize($ro)];}}
|
||||
|
||||
{my %ops =
|
||||
('+' => sub {$_[0] + $_[1]},
|
||||
'-' => sub {$_[0] - $_[1]},
|
||||
'*' => sub {$_[0] * $_[1]},
|
||||
'/' => sub {$_[0] / $_[1]});
|
||||
|
||||
sub ev_ast
|
||||
# Evaluates an abstract syntax tree of the form returned by
|
||||
# &astize.
|
||||
{my $ast = shift;
|
||||
# If $ast is just a number, return it as-is.
|
||||
ref $ast or return $ast;
|
||||
# Otherwise, recurse.
|
||||
my ($op, @operands) = @$ast;
|
||||
$_ = ev_ast($_) foreach @operands;
|
||||
return $ops{$op}->(@operands);}}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
(de ast (Str)
|
||||
(let *L (str Str "")
|
||||
(aggregate) ) )
|
||||
|
||||
(de aggregate ()
|
||||
(let X (product)
|
||||
(while (member (car *L) '("+" "-"))
|
||||
(setq X (list (intern (pop '*L)) X (product))) )
|
||||
X ) )
|
||||
|
||||
(de product ()
|
||||
(let X (term)
|
||||
(while (member (car *L) '("*" "/"))
|
||||
(setq X (list (intern (pop '*L)) X (term))) )
|
||||
X ) )
|
||||
|
||||
(de term ()
|
||||
(let X (pop '*L)
|
||||
(cond
|
||||
((num? X) X)
|
||||
((= "+" X) (term))
|
||||
((= "-" X) (list '- (term)))
|
||||
((= "(" X) (prog1 (aggregate) (pop '*L)))) ) ) )
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
: (ast "1+2+3*-4/(1+2)")
|
||||
-> (+ (+ 1 2) (/ (* 3 (- 4)) (+ 1 2)))
|
||||
|
||||
: (ast "(1+2+3)*-4/(1+2)")
|
||||
-> (/ (* (+ (+ 1 2) 3) (- 4)) (+ 1 2))
|
||||
50
Task/Arithmetic-evaluation/Prolog/arithmetic-evaluation.pro
Normal file
50
Task/Arithmetic-evaluation/Prolog/arithmetic-evaluation.pro
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
% Lexer
|
||||
numeric(X) :- 48 =< X, X =< 57.
|
||||
not_numeric(X) :- 48 > X ; X > 57.
|
||||
|
||||
lex1([], []).
|
||||
lex1([40|Xs], ['('|Ys]) :- lex1(Xs, Ys).
|
||||
lex1([41|Xs], [')'|Ys]) :- lex1(Xs, Ys).
|
||||
lex1([43|Xs], ['+'|Ys]) :- lex1(Xs, Ys).
|
||||
lex1([45|Xs], ['-'|Ys]) :- lex1(Xs, Ys).
|
||||
lex1([42|Xs], ['*'|Ys]) :- lex1(Xs, Ys).
|
||||
lex1([47|Xs], ['/'|Ys]) :- lex1(Xs, Ys).
|
||||
lex1([X|Xs], [N|Ys]) :- numeric(X), N is X - 48, lex1(Xs, Ys).
|
||||
|
||||
lex2([], []).
|
||||
lex2([X], [X]).
|
||||
lex2([Xa,Xb|Xs], [Xa|Ys]) :- atom(Xa), lex2([Xb|Xs], Ys).
|
||||
lex2([Xa,Xb|Xs], [Xa|Ys]) :- number(Xa), atom(Xb), lex2([Xb|Xs], Ys).
|
||||
lex2([Xa,Xb|Xs], [Y|Ys]) :- number(Xa), number(Xb), N is Xa * 10 + Xb, lex2([N|Xs], [Y|Ys]).
|
||||
|
||||
% Parser
|
||||
oper(1, *, X, Y, X * Y). oper(1, /, X, Y, X / Y).
|
||||
oper(2, +, X, Y, X + Y). oper(2, -, X, Y, X - Y).
|
||||
|
||||
num(D) --> [D], {number(D)}.
|
||||
|
||||
expr(0, Z) --> num(Z).
|
||||
expr(0, Z) --> {Z = (X)}, ['('], expr(2, X), [')'].
|
||||
|
||||
expr(N, Z) --> {succ(N0, N)}, {oper(N, Op, X, Y, Z)}, expr(N0, X), [Op], expr(N, Y).
|
||||
expr(N, Z) --> {succ(N0, N)}, expr(N0, Z).
|
||||
|
||||
parse(Tokens, Expr) :- expr(2, Expr, Tokens, []).
|
||||
|
||||
|
||||
% Evaluator
|
||||
evaluate(E, E) :- number(E).
|
||||
evaluate(A + B, E) :- evaluate(A, Ae), evaluate(B, Be), E is Ae + Be.
|
||||
evaluate(A - B, E) :- evaluate(A, Ae), evaluate(B, Be), E is Ae - Be.
|
||||
evaluate(A * B, E) :- evaluate(A, Ae), evaluate(B, Be), E is Ae * Be.
|
||||
evaluate(A / B, E) :- evaluate(A, Ae), evaluate(B, Be), E is Ae / Be.
|
||||
|
||||
% Solution
|
||||
calculator(String, Value) :-
|
||||
lex1(String, Tokens1),
|
||||
lex2(Tokens1, Tokens2),
|
||||
parse(Tokens2, Expression),
|
||||
evaluate(Expression, Value).
|
||||
|
||||
% Example use
|
||||
% calculator("(3+50)*7-9", X).
|
||||
116
Task/Arithmetic-evaluation/Python/arithmetic-evaluation-1.py
Normal file
116
Task/Arithmetic-evaluation/Python/arithmetic-evaluation-1.py
Normal file
|
|
@ -0,0 +1,116 @@
|
|||
import operator
|
||||
|
||||
class AstNode(object):
|
||||
def __init__( self, opr, left, right ):
|
||||
self.opr = opr
|
||||
self.l = left
|
||||
self.r = right
|
||||
|
||||
def eval(self):
|
||||
return self.opr(self.l.eval(), self.r.eval())
|
||||
|
||||
class LeafNode(object):
|
||||
def __init__( self, valStrg ):
|
||||
self.v = int(valStrg)
|
||||
|
||||
def eval(self):
|
||||
return self.v
|
||||
|
||||
class Yaccer(object):
|
||||
def __init__(self):
|
||||
self.operstak = []
|
||||
self.nodestak =[]
|
||||
self.__dict__.update(self.state1)
|
||||
|
||||
def v1( self, valStrg ):
|
||||
# Value String
|
||||
self.nodestak.append( LeafNode(valStrg))
|
||||
self.__dict__.update(self.state2)
|
||||
#print 'push', valStrg
|
||||
|
||||
def o2( self, operchar ):
|
||||
# Operator character or open paren in state1
|
||||
def openParen(a,b):
|
||||
return 0 # function should not be called
|
||||
|
||||
opDict= { '+': ( operator.add, 2, 2 ),
|
||||
'-': (operator.sub, 2, 2 ),
|
||||
'*': (operator.mul, 3, 3 ),
|
||||
'/': (operator.div, 3, 3 ),
|
||||
'^': ( pow, 4, 5 ), # right associative exponentiation for grins
|
||||
'(': ( openParen, 0, 8 )
|
||||
}
|
||||
operPrecidence = opDict[operchar][2]
|
||||
self.redeuce(operPrecidence)
|
||||
|
||||
self.operstak.append(opDict[operchar])
|
||||
self.__dict__.update(self.state1)
|
||||
# print 'pushop', operchar
|
||||
|
||||
def syntaxErr(self, char ):
|
||||
# Open Parenthesis
|
||||
print 'parse error - near operator "%s"' %char
|
||||
|
||||
def pc2( self,operchar ):
|
||||
# Close Parenthesis
|
||||
# reduce node until matching open paren found
|
||||
self.redeuce( 1 )
|
||||
if len(self.operstak)>0:
|
||||
self.operstak.pop() # pop off open parenthesis
|
||||
else:
|
||||
print 'Error - no open parenthesis matches close parens.'
|
||||
self.__dict__.update(self.state2)
|
||||
|
||||
def end(self):
|
||||
self.redeuce(0)
|
||||
return self.nodestak.pop()
|
||||
|
||||
def redeuce(self, precidence):
|
||||
while len(self.operstak)>0:
|
||||
tailOper = self.operstak[-1]
|
||||
if tailOper[1] < precidence: break
|
||||
|
||||
tailOper = self.operstak.pop()
|
||||
vrgt = self.nodestak.pop()
|
||||
vlft= self.nodestak.pop()
|
||||
self.nodestak.append( AstNode(tailOper[0], vlft, vrgt))
|
||||
# print 'reduce'
|
||||
|
||||
state1 = { 'v': v1, 'o':syntaxErr, 'po':o2, 'pc':syntaxErr }
|
||||
state2 = { 'v': syntaxErr, 'o':o2, 'po':syntaxErr, 'pc':pc2 }
|
||||
|
||||
|
||||
def Lex( exprssn, p ):
|
||||
bgn = None
|
||||
cp = -1
|
||||
for c in exprssn:
|
||||
cp += 1
|
||||
if c in '+-/*^()': # throw in exponentiation (^)for grins
|
||||
if bgn is not None:
|
||||
p.v(p, exprssn[bgn:cp])
|
||||
bgn = None
|
||||
if c=='(': p.po(p, c)
|
||||
elif c==')':p.pc(p, c)
|
||||
else: p.o(p, c)
|
||||
elif c in ' \t':
|
||||
if bgn is not None:
|
||||
p.v(p, exprssn[bgn:cp])
|
||||
bgn = None
|
||||
elif c in '0123456789':
|
||||
if bgn is None:
|
||||
bgn = cp
|
||||
else:
|
||||
print 'Invalid character in expression'
|
||||
if bgn is not None:
|
||||
p.v(p, exprssn[bgn:cp])
|
||||
bgn = None
|
||||
|
||||
if bgn is not None:
|
||||
p.v(p, exprssn[bgn:cp+1])
|
||||
bgn = None
|
||||
return p.end()
|
||||
|
||||
|
||||
expr = raw_input("Expression:")
|
||||
astTree = Lex( expr, Yaccer())
|
||||
print expr, '=',astTree.eval()
|
||||
24
Task/Arithmetic-evaluation/Python/arithmetic-evaluation-2.py
Normal file
24
Task/Arithmetic-evaluation/Python/arithmetic-evaluation-2.py
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
>>> import ast
|
||||
>>>
|
||||
>>> expr="2 * (3 -1) + 2 * 5"
|
||||
>>> node = ast.parse(expr, mode='eval')
|
||||
>>> print(ast.dump(node).replace(',', ',\n'))
|
||||
Expression(body=BinOp(left=BinOp(left=Num(n=2),
|
||||
op=Mult(),
|
||||
right=BinOp(left=Num(n=3),
|
||||
op=Sub(),
|
||||
right=Num(n=1))),
|
||||
op=Add(),
|
||||
right=BinOp(left=Num(n=2),
|
||||
op=Mult(),
|
||||
right=Num(n=5))))
|
||||
>>> code_object = compile(node, filename='<string>', mode='eval')
|
||||
>>> eval(code_object)
|
||||
14
|
||||
>>> # lets modify the AST by changing the 5 to a 6
|
||||
>>> node.body.right.right.n
|
||||
5
|
||||
>>> node.body.right.right.n = 6
|
||||
>>> code_object = compile(node, filename='<string>', mode='eval')
|
||||
>>> eval(code_object)
|
||||
16
|
||||
117
Task/Arithmetic-evaluation/REXX/arithmetic-evaluation.rexx
Normal file
117
Task/Arithmetic-evaluation/REXX/arithmetic-evaluation.rexx
Normal file
|
|
@ -0,0 +1,117 @@
|
|||
/*REXX pgm evaluates an infix-type arithmetic expression & shows result.*/
|
||||
nchars = '0123456789.eEdDqQ' /*possible parts of a #, sans ± */
|
||||
e='***error!***'; $=' '; doubleOps='&|*/'; z=
|
||||
parse arg x 1 ox1; if x='' then call serr 'no input was specified.'
|
||||
x=space(x); L=length(x); x=translate(x,'()()',"[]{}")
|
||||
|
||||
j=0; do forever; j=j+1; if j>L then leave; _=substr(x,j,1); _2=getX()
|
||||
newT=pos(_,' ()[]{}^÷')\==0; if newT then do; z=z _ $; iterate; end
|
||||
possDouble=pos(_,doubleOps)\==0 /*is _ a possible double operator*/
|
||||
if possDouble then do /*is this a possible double oper?*/
|
||||
if _2==_ then do /*yup, it's one of 'em.*/
|
||||
_=_||_ /*use a double operator*/
|
||||
x=overlay($,x,Nj) /*blank out the*/
|
||||
end /* 2nd symbol.*/
|
||||
z=z _ $; iterate
|
||||
end
|
||||
if _=='+' | _=="-" then do; p_=word(z,words(z)) /*last Z token*/
|
||||
if p_=='(' then z=z 0 /handle unary ±*/
|
||||
z=z _ $; iterate
|
||||
end
|
||||
lets=0; sigs=0; #=_
|
||||
|
||||
do j=j+1 to L; _=substr(x,j,1) /*build a valid number.*/
|
||||
if lets==1 & sigs==0 then if _=='+' | _=='-' then do; sigs=1
|
||||
#=# || _
|
||||
iterate
|
||||
end /*exp*/
|
||||
if pos(_,nchars)==0 then leave
|
||||
lets=lets+datatype(_,'M') /*keep track of # of exponents. */
|
||||
#=# || translate(_,'EEEEE','eDdQq') /*keep buildingthe num.*/
|
||||
end /*j*/
|
||||
j=j-1
|
||||
if \datatype(#,'N') then call serr 'invalid number: ' #
|
||||
z=z # $
|
||||
end /*forever*/
|
||||
|
||||
_=word(z,1); if _=='+' | _=='-' then z=0 z /*handle unary cases.*/
|
||||
x='(' space(z) ') '; tokens=words(x) /*force stacking for expression. */
|
||||
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. */
|
||||
op=')(-+/*^'; rOp=substr(op,3); p.=; s.=; n=length(op); epr=; stack=
|
||||
|
||||
do i=1 for n; _=substr(op,i,1); s._=(i+1)%2; p._=s._+(i==n); end /*i*/
|
||||
/*[↑] assign operator priorities.*/
|
||||
do #=1 for tokens; ?=@.# /*process each token from @. list*/
|
||||
if ?=='**' then ?="^" /*convert REXX-type exponentation*/
|
||||
select /*@.# is: (, operator, ), operand*/
|
||||
when ?=='(' then stack='(' stack
|
||||
when isOp(?) then do /*is token an operator?*/
|
||||
!=word(stack,1) /*get token from stack.*/
|
||||
do while !\==')' & s.!>=p.?; epr=epr ! /*add*/
|
||||
stack=subword(stack,2); /*del token from stack.*/
|
||||
!=word(stack,1) /*get token from stack.*/
|
||||
end /*while ···)*/
|
||||
stack=? stack /*add token to stack.*/
|
||||
end
|
||||
when ?==')' then do; !=word(stack,1) /*get token from stack.*/
|
||||
do while !\=='('; epr=epr ! /*add to epr.*/
|
||||
stack=subword(stack,2) /*del token from stack.*/
|
||||
!=word(stack,1) /*get token from stack.*/
|
||||
end /*while ···( */
|
||||
stack=subword(stack,2) /*del token from stack.*/
|
||||
end
|
||||
otherwise epr=epr ? /*add operand to epr. */
|
||||
end /*select*/
|
||||
end /*#*/
|
||||
|
||||
epr=space(epr stack); tokens=words(epr); x=epr; z=; stack=
|
||||
do i=1 for tokens; @.i=word(epr,i); end /*i*/ /*assign input tokens*/
|
||||
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 ?; iterate; end
|
||||
if wordpos(?,lop)==0 then do; z=e 'illegal operator:' ?; leave; end
|
||||
if w<2 then do; z=e 'illegal epr 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
|
||||
select /*perform arith. operation*/
|
||||
when ??=='+' then y = a + b
|
||||
when ??=='-' then y = a - b
|
||||
when ??=='*' then y = a * b
|
||||
when ??=='/' | ??=="÷" then y = a / b
|
||||
when ??=='//' then y = a // b
|
||||
when ??=='%' then y = a % b
|
||||
when ??=='^' | ??=="**" then y = a ** b
|
||||
when ??=='||' then y = a || b
|
||||
otherwise z=e 'invalid operator:' ?; leave
|
||||
end /*select*/
|
||||
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. */
|
||||
end /*#*/
|
||||
|
||||
if word(z,1)==e then stack= /*handle special case of errors. */
|
||||
z=space(z stack) /*append any residual entries. */
|
||||
say 'answer──►' z /*display the answer (result). */
|
||||
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.*/
|
||||
isOp: return pos(arg(1),rOp)\==0 /*is argument1 a "real" operator?*/
|
||||
serr: say; say e arg(1); say; exit 13 /*issue an error message with txt*/
|
||||
/*──────────────────────────────────GETX subroutine─────────────────────*/
|
||||
getX: do Nj=j+1 to length(x); _n=substr(x,Nj,1); if _n==$ then iterate
|
||||
if _n==$ then iterate; return substr(x,Nj,1) /*ignore blanks*/
|
||||
end /*Nj*/
|
||||
return $ /*reached end-of-tokens, return $*/
|
||||
96
Task/Arithmetic-evaluation/Ruby/arithmetic-evaluation-1.rb
Normal file
96
Task/Arithmetic-evaluation/Ruby/arithmetic-evaluation-1.rb
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
$op_priority = {"+" => 0, "-" => 0, "*" => 1, "/" => 1}
|
||||
$op_function = {
|
||||
"+" => lambda {|x, y| x + y},
|
||||
"-" => lambda {|x, y| x - y},
|
||||
"*" => lambda {|x, y| x * y},
|
||||
"/" => lambda {|x, y| x / y}}
|
||||
|
||||
class TreeNode
|
||||
attr_accessor :info, :left, :right
|
||||
|
||||
def initialize(info)
|
||||
@info = info
|
||||
end
|
||||
|
||||
def leaf?
|
||||
@left.nil? and @right.nil?
|
||||
end
|
||||
|
||||
def to_s(order)
|
||||
if leaf?
|
||||
@info
|
||||
else
|
||||
left_s, right_s = @left.to_s(order), @right.to_s(order)
|
||||
|
||||
strs = case order
|
||||
when :prefix then [@info, left_s, right_s]
|
||||
when :infix then [left_s, @info, right_s]
|
||||
when :postfix then [left_s, right_s, @info]
|
||||
else []
|
||||
end
|
||||
|
||||
"(" + strs.join(" ") + ")"
|
||||
end
|
||||
end
|
||||
|
||||
def eval
|
||||
if !leaf? and operator?(@info)
|
||||
$op_function[@info].call(@left.eval, @right.eval)
|
||||
else
|
||||
@info.to_f
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def tokenize(exp)
|
||||
exp
|
||||
.gsub('(', ' ( ')
|
||||
.gsub(')', ' ) ')
|
||||
.split(' ')
|
||||
end
|
||||
|
||||
def operator?(token)
|
||||
$op_priority.has_key?(token)
|
||||
end
|
||||
|
||||
def pop_connect_push(op_stack, node_stack)
|
||||
temp = op_stack.pop
|
||||
temp.right = node_stack.pop
|
||||
temp.left = node_stack.pop
|
||||
node_stack.push(temp)
|
||||
end
|
||||
|
||||
def infix_exp_to_tree(exp)
|
||||
tokens = tokenize(exp)
|
||||
op_stack, node_stack = [], []
|
||||
|
||||
tokens.each do |token|
|
||||
if operator?(token)
|
||||
# clear stack of higher priority operators
|
||||
until (op_stack.empty? or
|
||||
op_stack.last.info == "(" or
|
||||
$op_priority[op_stack.last.info] < $op_priority[token])
|
||||
pop_connect_push(op_stack, node_stack)
|
||||
end
|
||||
|
||||
op_stack.push(TreeNode.new(token))
|
||||
elsif token == "("
|
||||
op_stack.push(TreeNode.new(token))
|
||||
elsif token == ")"
|
||||
while op_stack.last.info != "("
|
||||
pop_connect_push(op_stack, node_stack)
|
||||
end
|
||||
|
||||
# throw away the '('
|
||||
op_stack.pop
|
||||
else
|
||||
node_stack.push(TreeNode.new(token))
|
||||
end
|
||||
end
|
||||
|
||||
until op_stack.empty?
|
||||
pop_connect_push(op_stack, node_stack)
|
||||
end
|
||||
|
||||
node_stack.last
|
||||
end
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
exp = "1 + 2 - 3 * (4 / 6)"
|
||||
puts("Original: " + exp)
|
||||
|
||||
tree = infix_exp_to_tree(exp)
|
||||
puts("Prefix: " + tree.to_s(:prefix))
|
||||
puts("Infix: " + tree.to_s(:infix))
|
||||
puts("Postfix: " + tree.to_s(:postfix))
|
||||
puts("Result: " + tree.eval.to_s)
|
||||
46
Task/Arithmetic-evaluation/Scala/arithmetic-evaluation.scala
Normal file
46
Task/Arithmetic-evaluation/Scala/arithmetic-evaluation.scala
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
package org.rosetta.arithmetic_evaluator.scala
|
||||
|
||||
object ArithmeticParser extends scala.util.parsing.combinator.RegexParsers {
|
||||
|
||||
def readExpression(input: String) : Option[()=>Int] = {
|
||||
parseAll(expr, input) match {
|
||||
case Success(result, _) =>
|
||||
Some(result)
|
||||
case other =>
|
||||
println(other)
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
private def expr : Parser[()=>Int] = {
|
||||
(term<~"+")~expr ^^ { case l~r => () => l() + r() } |
|
||||
(term<~"-")~expr ^^ { case l~r => () => l() - r() } |
|
||||
term
|
||||
}
|
||||
|
||||
private def term : Parser[()=>Int] = {
|
||||
(factor<~"*")~term ^^ { case l~r => () => l() * r() } |
|
||||
(factor<~"/")~term ^^ { case l~r => () => l() / r() } |
|
||||
factor
|
||||
}
|
||||
|
||||
private def factor : Parser[()=>Int] = {
|
||||
"("~>expr<~")" |
|
||||
"\\d+".r ^^ { x => () => x.toInt } |
|
||||
failure("Expected a value")
|
||||
}
|
||||
}
|
||||
|
||||
object Main {
|
||||
def main(args: Array[String]) {
|
||||
println("""Please input the expressions. Type "q" to quit.""")
|
||||
var input: String = ""
|
||||
|
||||
do {
|
||||
input = readLine("> ")
|
||||
if (input != "q") {
|
||||
ArithmeticParser.readExpression(input).foreach(f => println(f()))
|
||||
}
|
||||
} while (input != "q")
|
||||
}
|
||||
}
|
||||
44
Task/Arithmetic-evaluation/Tcl/arithmetic-evaluation.tcl
Normal file
44
Task/Arithmetic-evaluation/Tcl/arithmetic-evaluation.tcl
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
namespace import tcl::mathop::*
|
||||
|
||||
proc ast str {
|
||||
# produce abstract syntax tree for an expression
|
||||
regsub -all {[-+*/()]} $str { & } str ;# "tokenizer"
|
||||
s $str
|
||||
}
|
||||
proc s {args} {
|
||||
# parse "(a + b) * c + d" to "+ [* [+ a b] c] d"
|
||||
if {[llength $args] == 1} {set args [lindex $args 0]}
|
||||
if [regexp {[()]} $args] {
|
||||
eval s [string map {( "\[s " ) \]} $args]
|
||||
} elseif {"*" in $args} {
|
||||
s [s_group $args *]
|
||||
} elseif {"/" in $args} {
|
||||
s [s_group $args /]
|
||||
} elseif {"+" in $args} {
|
||||
s [s_group $args +]
|
||||
} elseif {"-" in $args} {
|
||||
s [s_group $args -]
|
||||
} else {
|
||||
string map {\{ \[ \} \]} [join $args]
|
||||
}
|
||||
}
|
||||
proc s_group {list op} {
|
||||
# turn ".. a op b .." to ".. {op a b} .."
|
||||
set pos [lsearch -exact $list $op]
|
||||
set p_1 [- $pos 1]
|
||||
set p1 [+ $pos 1]
|
||||
lreplace $list $p_1 $p1 \
|
||||
[list $op [lindex $list $p_1] [lindex $list $p1]]
|
||||
}
|
||||
#-- Test suite
|
||||
foreach test [split {
|
||||
ast 2-2
|
||||
ast 1-2-3
|
||||
ast (1-2)-3
|
||||
ast 1-(2-3)
|
||||
ast (1+2)*3
|
||||
ast (1+2)/3-4*5
|
||||
ast ((1+2)/3-4)*5
|
||||
} \n] {
|
||||
puts "$test ..... [eval $test] ..... [eval [eval $test]]"
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue