diff --git a/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/stack/expr/InfixExpr.java b/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/stack/expr/InfixExpr.java new file mode 100644 index 0000000000..d3e9afbf9b --- /dev/null +++ b/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/stack/expr/InfixExpr.java @@ -0,0 +1,19 @@ +package com.johnChnia.coding2017.basic.stack.expr; + + +import com.johnChnia.coding2017.basic.List; + +public class InfixExpr { + String expr = null; + + public InfixExpr(String expr) { + this.expr = expr; + } + + public float evaluate() { + List tokens = InfixToPostfix.convert(this.expr); + return PostfixExpr.evaluate(tokens); + } + + +} diff --git a/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/stack/expr/InfixExprTest.java b/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/stack/expr/InfixExprTest.java new file mode 100644 index 0000000000..e47a8841da --- /dev/null +++ b/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/stack/expr/InfixExprTest.java @@ -0,0 +1,52 @@ +package com.johnChnia.coding2017.basic.stack.expr; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + + +public class InfixExprTest { + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testEvaluate() { + //InfixExpr expr = new InfixExpr("300*20+12*5-20/4"); + { + InfixExpr expr = new InfixExpr("2+3*4+5"); + Assert.assertEquals(19.0, expr.evaluate(), 0.001f); + } + { + InfixExpr expr = new InfixExpr("3*20+12*5-40/2"); + Assert.assertEquals(100.0, expr.evaluate(), 0.001f); + } + + { + InfixExpr expr = new InfixExpr("3*20/2"); + Assert.assertEquals(30, expr.evaluate(), 0.001f); + } + + { + InfixExpr expr = new InfixExpr("20/2*3"); + Assert.assertEquals(30, expr.evaluate(), 0.001f); + } + + { + InfixExpr expr = new InfixExpr("10-30+50"); + Assert.assertEquals(30, expr.evaluate(), 0.001f); + } + { + InfixExpr expr = new InfixExpr("10-2*3+50"); + Assert.assertEquals(54, expr.evaluate(), 0.001f); + } + + } + +} diff --git a/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/stack/expr/InfixToPostfix.java b/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/stack/expr/InfixToPostfix.java new file mode 100644 index 0000000000..e361815f02 --- /dev/null +++ b/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/stack/expr/InfixToPostfix.java @@ -0,0 +1,37 @@ +package com.johnChnia.coding2017.basic.stack.expr; + + +import com.johnChnia.coding2017.basic.ArrayList; +import com.johnChnia.coding2017.basic.List; +import com.johnChnia.coding2017.basic.stack.Stack; + + +/*** + * Rule: + */ +public class InfixToPostfix { + + public static List convert(String expr) { + TokenParser tokenParser = new TokenParser(); + List tokens = tokenParser.parse(expr); + List list = new ArrayList<>(); + Stack stack = new Stack<>(); + for (int i = 0; i < tokens.size(); i++) { + Token token = tokens.get(i); + if (token.isNumber()) { + list.add(token); + } else if (token.isOperator()) { + while (!stack.empty() && !token.hasHigherPriority(stack.peek())) { + list.add(stack.pop()); + } + stack.push(token); + + } + } + while (!stack.empty()) { + list.add(stack.pop()); + } + return list; + } + +} diff --git a/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/stack/expr/Operator.java b/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/stack/expr/Operator.java new file mode 100644 index 0000000000..adc1aac489 --- /dev/null +++ b/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/stack/expr/Operator.java @@ -0,0 +1,42 @@ +package com.johnChnia.coding2017.basic.stack.expr; + +import com.johnChnia.coding2017.basic.stack.Stack; + +/** + * Created by john on 2017/4/20. + */ +public class Operator { + + public void handlerToken(String fix, Stack stack, Token token) { + if (token.isNumber()) { + stack.push(Float.parseFloat(token.toString())); + } else if (token.isOperator()) { + float p = stack.pop(); + float q = stack.pop(); + stack.push(perform(fix, token.toString(), p, q)); + } + } + + + private float perform(String fix, String operator, float p, float q) { + float result = 0.0f; + if (operator.equals("+")) { + result = p + q; + } else if (operator.equals("-")) { + if (fix.equals("postfix")) { + result = q - p; + } else if (fix.equals("prefix")) { + result = p - q; + } + } else if (operator.equals("*")) { + result = p * q; + } else if (operator.equals("/")) { + if (fix.equals("postfix")) { + result = q / p; + } else if (fix.equals("prefix")) { + result = p / q; + } + } + return result; + } +} diff --git a/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/stack/expr/PostfixExpr.java b/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/stack/expr/PostfixExpr.java new file mode 100644 index 0000000000..4046c13830 --- /dev/null +++ b/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/stack/expr/PostfixExpr.java @@ -0,0 +1,36 @@ +package com.johnChnia.coding2017.basic.stack.expr; + +import com.johnChnia.coding2017.basic.List; +import com.johnChnia.coding2017.basic.stack.Stack; + +public class PostfixExpr { + private String expr = null; + static Operator operator = new Operator(); + + + public PostfixExpr(String expr) { + this.expr = expr; + } + + public float evaluate() { + TokenParser tokenParser = new TokenParser(); + List tokens = tokenParser.parse(this.expr); + Stack stack = new Stack<>(); + for (int i = 0; i < tokens.size(); i++) { + operator.handlerToken("postfix", stack, tokens.get(i)); + + } + + return stack.pop(); + } + + public static float evaluate(List tokens) { + Stack stack = new Stack<>(); + for (int i = 0; i < tokens.size(); i++) { + operator.handlerToken("postfix", stack, tokens.get(i)); + } + return stack.pop(); + } + + +} diff --git a/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/stack/expr/PostfixExprTest.java b/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/stack/expr/PostfixExprTest.java new file mode 100644 index 0000000000..312eed28b3 --- /dev/null +++ b/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/stack/expr/PostfixExprTest.java @@ -0,0 +1,41 @@ +package com.johnChnia.coding2017.basic.stack.expr; + + + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + + + +public class PostfixExprTest { + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testEvaluate() { + { + PostfixExpr expr = new PostfixExpr("6 5 2 3 + 8 * + 3 + *"); + Assert.assertEquals(288, expr.evaluate(),0.0f); + } + { + //9+(3-1)*3+10/2 + PostfixExpr expr = new PostfixExpr("9 3 1-3*+ 10 2/+"); + Assert.assertEquals(20, expr.evaluate(),0.0f); + } + + { + //10-2*3+50 + PostfixExpr expr = new PostfixExpr("10 2 3 * - 50 +"); + Assert.assertEquals(54, expr.evaluate(),0.0f); + } + } + +} diff --git a/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/stack/expr/PrefixExpr.java b/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/stack/expr/PrefixExpr.java new file mode 100644 index 0000000000..c16f529845 --- /dev/null +++ b/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/stack/expr/PrefixExpr.java @@ -0,0 +1,25 @@ +package com.johnChnia.coding2017.basic.stack.expr; + +import com.johnChnia.coding2017.basic.List; +import com.johnChnia.coding2017.basic.stack.Stack; + +public class PrefixExpr { + String expr = null; + + public PrefixExpr(String expr) { + this.expr = expr; + } + + public float evaluate() { + TokenParser tokenParser = new TokenParser(); + List tokens = tokenParser.parse(this.expr); + Operator operator = new Operator(); + Stack stack = new Stack<>(); + for (int i = tokens.size() - 1; i >= 0; i--) { + operator.handlerToken("prefix", stack, tokens.get(i)); + } + return stack.pop(); + } + + +} diff --git a/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/stack/expr/PrefixExprTest.java b/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/stack/expr/PrefixExprTest.java new file mode 100644 index 0000000000..30f67b2710 --- /dev/null +++ b/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/stack/expr/PrefixExprTest.java @@ -0,0 +1,45 @@ +package com.johnChnia.coding2017.basic.stack.expr; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + + +public class PrefixExprTest { + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testEvaluate() { + { + // 2*3+4*5 + PrefixExpr expr = new PrefixExpr("+ * 2 3* 4 5"); + Assert.assertEquals(26, expr.evaluate(), 0.001f); + } + { + // 4*2 + 6+9*2/3 -8 + PrefixExpr expr = new PrefixExpr("-++6/*2 9 3 * 4 2 8"); + Assert.assertEquals(12, expr.evaluate(), 0.001f); + } + { + //(3+4)*5-6 + PrefixExpr expr = new PrefixExpr("- * + 3 4 5 6"); + Assert.assertEquals(29, expr.evaluate(), 0.001f); + } + { + //1+((2+3)*4)-5 + PrefixExpr expr = new PrefixExpr("- + 1 * + 2 3 4 5"); + Assert.assertEquals(16, expr.evaluate(), 0.001f); + } + + + } + +} diff --git a/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/stack/expr/Token.java b/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/stack/expr/Token.java new file mode 100644 index 0000000000..f87a210587 --- /dev/null +++ b/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/stack/expr/Token.java @@ -0,0 +1,50 @@ +package com.johnChnia.coding2017.basic.stack.expr; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +class Token { + public static final List OPERATORS = Arrays.asList("+", "-", "*", "/"); + private static final Map priorities = new HashMap<>(); + static { + priorities.put("+", 1); + priorities.put("-", 1); + priorities.put("*", 2); + priorities.put("/", 2); + } + static final int OPERATOR = 1; + static final int NUMBER = 2; + String value; + int type; + public Token(int type, String value){ + this.type = type; + this.value = value; + } + + public boolean isNumber() { + return type == NUMBER; + } + + public boolean isOperator() { + return type == OPERATOR; + } + + public int getIntValue() { + return Integer.valueOf(value).intValue(); + } + public String toString(){ + return value; + } + + public boolean hasHigherPriority(Token t){ + if(!this.isOperator() && !t.isOperator()){ + throw new RuntimeException("numbers can't compare priority"); + } + return priorities.get(this.value) - priorities.get(t.value) > 0; + } + + + +} \ No newline at end of file diff --git a/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/stack/expr/TokenParser.java b/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/stack/expr/TokenParser.java new file mode 100644 index 0000000000..b9c8b80444 --- /dev/null +++ b/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/stack/expr/TokenParser.java @@ -0,0 +1,58 @@ +package com.johnChnia.coding2017.basic.stack.expr; + + +import com.johnChnia.coding2017.basic.ArrayList; +import com.johnChnia.coding2017.basic.List; + +public class TokenParser { + + + public List parse(String expr) { + List tokens = new ArrayList<>(); + + int i = 0; + + while (i < expr.length()) { + + char c = expr.charAt(i); + + if (isOperator(c)) { + + Token t = new Token(Token.OPERATOR, String.valueOf(c)); + tokens.add(t); + i++; + + } else if (Character.isDigit(c)) { + + int nextOperatorIndex = indexOfNextOperator(i, expr); + String value = expr.substring(i, nextOperatorIndex); + Token t = new Token(Token.NUMBER, value); + tokens.add(t); + i = nextOperatorIndex; + + } else { + System.out.println("char :[" + c + "] is not number or operator,ignore"); + i++; + } + + } + return tokens; + } + + private int indexOfNextOperator(int i, String expr) { + + while (Character.isDigit(expr.charAt(i))) { + i++; + if (i == expr.length()) { + break; + } + } + return i; + + } + + private boolean isOperator(char c) { + String sc = String.valueOf(c); + return Token.OPERATORS.contains(sc); + } +} diff --git a/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/stack/expr/TokenParserTest.java b/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/stack/expr/TokenParserTest.java new file mode 100644 index 0000000000..cdb3b091db --- /dev/null +++ b/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/stack/expr/TokenParserTest.java @@ -0,0 +1,39 @@ +package com.johnChnia.coding2017.basic.stack.expr; + +import com.johnChnia.coding2017.basic.List; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + + +public class TokenParserTest { + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void test() { + + TokenParser parser = new TokenParser(); + List tokens = parser.parse("300*20+12*5-20/4"); + + Assert.assertEquals(300, tokens.get(0).getIntValue()); + Assert.assertEquals("*", tokens.get(1).toString()); + Assert.assertEquals(20, tokens.get(2).getIntValue()); + Assert.assertEquals("+", tokens.get(3).toString()); + Assert.assertEquals(12, tokens.get(4).getIntValue()); + Assert.assertEquals("*", tokens.get(5).toString()); + Assert.assertEquals(5, tokens.get(6).getIntValue()); + Assert.assertEquals("-", tokens.get(7).toString()); + Assert.assertEquals(20, tokens.get(8).getIntValue()); + Assert.assertEquals("/", tokens.get(9).toString()); + Assert.assertEquals(4, tokens.get(10).getIntValue()); + } + +}