ForNext
Only Do What Only You Can Do
Interpreter
VBScript
JScript
Perl
PHP
Python
Ruby
PowerShell
Scala
F#
C
C++
C++Builder
VC++
C#
Java
更新日 : 2010.12.02
■ Step 1
■ MyMain
public class MyMain { public static void main(String args[]) { if (args.length < 3) return; Operator ope; if (args[0].equals("add")) ope = new Addition(); else if (args[0].equals("sub")) ope = new Subtraction(); else return; IntOperand op1 = new IntOperand(Integer.parseInt(args[1])); IntOperand op2 = new IntOperand(Integer.parseInt(args[2])); Expression exp = new Expression(ope, op1, op2); System.out.println(exp.getValue()); } }
■ Operator
public interface Operator { // 左側のオペランド public void setOperand1(Operand operand); // 右側のオペランド public void setOperand2(Operand operand); // 演算を実行 public int calc(); }
■ Operand
public interface Operand { // オペランドの値を返す public int getValue(); }
■ IntOperand
// 整数オペランド public class IntOperand implements Operand { private int value; public IntOperand(int value) { this.value = value; } public int getValue() { return value; } }
■ Expression
// 演算式 public class Expression implements Operand { private Operator operator; public Expression(Operator operator, Operand operand1, Operand operand2) { this.operator = operator; // 左側のオペランド this.operator.setOperand1(operand1); // 右側のオペランド this.operator.setOperand2(operand2); } public int getValue() { // 演算を実行 return operator.calc(); } }
■ Addition
// + public class Addition implements Operator { private Operand operand1; private Operand operand2; // 左側のオペランド public void setOperand1(Operand operand) { this.operand1 = operand; } // 右側のオペランド public void setOperand2(Operand operand) { this.operand2 = operand; } // 演算を実行 public int calc() { return operand1.getValue() + operand2.getValue(); } }
■ Subtraction
// - public class Subtraction implements Operator { private Operand operand1; private Operand operand2; // 左側のオペランド public void setOperand1(Operand operand) { this.operand1 = operand; } // 右側のオペランド public void setOperand2(Operand operand) { this.operand2 = operand; } // 演算を実行 public int calc() { return operand1.getValue() - operand2.getValue(); } }
L:\>java MyMain add 2 3 5 L:\>java MyMain sub 17 35 -18
■ Step 2 逆ポーランド記法を評価
■ MyMain
import java.util.*; public class MyMain { public static void main(String args[]) { String exp = "(6 + 3) / (6 - 2) + 3 * 2 ^ 3 - 1"; // 演算子の優先順位表を作成 Map<String, Integer> priMap = new HashMap<String, Integer>(); priMap.put("+", 1); priMap.put("-", 1); priMap.put("*", 2); priMap.put("/", 2); priMap.put("%", 2); priMap.put("^", 3); priMap.put("(", 5); priMap.put(")", 0); for (Integer i = 0; i <= 9; i++) priMap.put(i.toString(), 4); List<String> stack = new ArrayList<String>(); List<String> polish = new ArrayList<String>(); stack.add(" "); priMap.put(" ", -1); for (int i = 0; i < exp.length(); i++) { // 1桁の数値にしか対応していない String token = exp.substring(i, i+1); if (token.trim().length() <= 0) continue; Integer pri1 = priMap.get(token); Integer pri2 = priMap.get(stack.get(stack.size() - 1)); if (pri1 == null) continue; if (pri2 == null) continue; while (pri1 <= pri2) { if (stack.get(stack.size() - 1).equals("(")) break; // stack から取り出し、polish に積む if (stack.size() > 0) { polish.add(stack.get(stack.size() - 1)); stack.remove(stack.size() - 1); pri2 = priMap.get(stack.get(stack.size() - 1)); if (pri2 == null) continue; } } if (!token.equals(")")) { // stack に積む stack.add(token); } else { // stack から取り出し stack.remove(stack.size() - 1); } } // stack から取り出し、polish に積む for (int i = stack.size() - 1; i >= 0; i--) { polish.add(stack.get(i)); } System.out.print("与えられた式:"); System.out.println(exp); System.out.print("逆ポーランド記法に変換後の式:"); for (int j = 0; j < polish.size(); j++) System.out.print(polish.get(j)); System.out.println(); // 式を評価 List<String> operandList = new ArrayList<String>(); for (int i = 0; i < polish.size(); i++) { if(polish.get(i).matches("[0-9]*")) { operandList.add(polish.get(i)); } else if ( (polish.get(i).equals("+")) || (polish.get(i).equals("-")) || (polish.get(i).equals("*")) || (polish.get(i).equals("/")) || (polish.get(i).equals("%")) || (polish.get(i).equals("^")) ) { IntOperand op1 = new IntOperand(Integer.parseInt(operandList.get(operandList.size() - 2))); IntOperand op2 = new IntOperand(Integer.parseInt(operandList.get(operandList.size() - 1))); Operator ope = null; if (polish.get(i).equals("+")) ope = new Add(); else if (polish.get(i).equals("-")) ope = new Sub(); else if (polish.get(i).equals("*")) ope = new Mul(); else if (polish.get(i).equals("/")) ope = new Div(); else if (polish.get(i).equals("%")) ope = new Mod(); else if (polish.get(i).equals("^")) ope = new Pow(); if (ope != null) { Expression expr = new Expression(ope, op1, op2); System.out.print(operandList.get(operandList.size() - 2)); System.out.print(polish.get(i)); System.out.print(operandList.get(operandList.size() - 1)); System.out.print("="); System.out.println(expr.getValue()); operandList.set(operandList.size() - 2, Integer.toString(expr.getValue())); } operandList.remove(operandList.size() - 1); } } System.out.print("答え:"); System.out.println(operandList.get(operandList.size() - 1)); } }
■ Operand
// オペランド インターフェース public interface Operand { // オペランドの値を返す public int getValue(); }
■ IntOperand
// 整数オペランド public class IntOperand implements Operand { private int value; public IntOperand(int value) { this.value = value; } public int getValue() { return value; } }
■ Expression
// 演算式オペランド public class Expression implements Operand { private Operator operator; public Expression(Operator operator, Operand operand1, Operand operand2) { this.operator = operator; // 左側のオペランド this.operator.setOperand1(operand1); // 右側のオペランド this.operator.setOperand2(operand2); } public int getValue() { // 演算を実行 return operator.calc(); } }
■ Operator
public abstract class Operator { protected Operand operand1; protected Operand operand2; // 左側のオペランド public void setOperand1(Operand operand) { this.operand1 = operand; } // 右側のオペランド public void setOperand2(Operand operand) { this.operand2 = operand; } // 演算を実行 public abstract int calc(); }
■ Add
// 加 public class Add extends Operator { public int calc() { return operand1.getValue() + operand2.getValue(); } }
■ Sub
// 減 public class Sub extends Operator { public int calc() { return operand1.getValue() - operand2.getValue(); } }
■ Mul
// 乗 public class Mul extends Operator { public int calc() { return operand1.getValue() * operand2.getValue(); } }
■ Div
// 除 public class Div extends Operator { public int calc() { return operand1.getValue() / operand2.getValue(); } }
■ Mod
// 剰余 public class Mod extends Operator { public int calc() { return operand1.getValue() % operand2.getValue(); } }
■ Pow
// べき乗 public class Pow extends Operator { public int calc() { return (int)Math.pow(operand1.getValue(), operand2.getValue()); } }
L:\>java MyMain 与えられた式:(6 + 3) / (6 - 2) + 3 * 2 ^ 3 - 1 逆ポーランド記法に変換後の式:63+62-/323^*+1- 6+3=9 6-2=4 9/4=2 2^3=8 3*8=24 2+24=26 26-1=25 答え:25
■ Step 3 前置記法を評価する
■ MyMain
public class MyMain { public static void main(String args[]) { String text = "(- (+ (/ (+ 6 3) (- 6 2)) (* 3 (^ 2 3))) 1)"; Node node = new ExpressionNode(); try { node.parse(new Context(text)); System.out.print(node.toString() + " = "); System.out.println(node.getValue()); } catch (Exception e) { System.err.println(e); } } }
■ Context
class Context { private int pos; private String text; private String currToken; private int currTokenType; private static final int LPAREN = 0; private static final int ALPHA = 1; private static final int OPERATOR = 2; private static final int DIGIT = 3; private static final int RPAREN = 4; private static final int UNKNOWN = -1; private static final String lparen = "("; private static final String alpha = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; private static final String operator = "+-*/^"; private static final String digit = "0123456789"; private static final String rparen = ")"; public Context(String text) { this.text = text; pos = 0; currToken = ""; currTokenType = UNKNOWN; // 最初の token を 読み込む nextToken(); } public String nextToken() { // 次の token を 読み込む int nextTokenType = UNKNOWN; currTokenType = UNKNOWN; while (pos < text.length()) { char c = text.charAt(pos); if (lparen.indexOf(c) >= 0) nextTokenType = LPAREN; else if (alpha.indexOf(c) >= 0) nextTokenType = ALPHA; else if (operator.indexOf(c) >= 0) nextTokenType = OPERATOR; else if (digit.indexOf(c) >= 0) nextTokenType = DIGIT; else if (rparen.indexOf(c) >= 0) nextTokenType = RPAREN; else nextTokenType = UNKNOWN; if (currTokenType == nextTokenType) { if ((currTokenType != LPAREN) && (currTokenType != RPAREN)) { if (nextTokenType != UNKNOWN) currToken += c; pos++; continue; } } if (currTokenType == UNKNOWN) { currTokenType = nextTokenType; currToken = String.valueOf(c); pos++; } else { return currToken; } } return currToken; } public String currToken() { return currToken; } public void skipToken(String token) throws Exception { if (!token.equals(currToken)) { throw new Exception(token + " が あるべきべきところに、" + currToken + " が ある"); } nextToken(); } }
■ Node
abstract class Node { public abstract void parse(Context context) throws Exception; public abstract int getValue() throws Exception; }
■ ExpressionNode
// <expression> ::= <left paren> <operator> <operand> <operand> <right paren> class ExpressionNode extends Node { private OperatorNode operator; private OperandNode operand1; private OperandNode operand2; public void parse(Context context) throws Exception { context.skipToken("("); operator = new OperatorNode(); operator.parse(context); operand1 = new OperandNode(); operand1.parse(context); operand2 = new OperandNode(); operand2.parse(context); context.skipToken(")"); } public String toString() { return "(" + operator + " " + operand1 + " " + operand2 + ")"; } public int getValue() throws Exception { int n1 = operand1.getValue(); int n2 = operand2.getValue(); int result = 0; if (operator.toString().equals("+")) result = n1 + n2; else if (operator.toString().equals("-")) result = n1 - n2; else if (operator.toString().equals("*")) result = n1 * n2; else if (operator.toString().equals("/")) result = n1 / n2; else if (operator.toString().equals("^")) result = (int)Math.pow(n1, n2); return result; } }
■ OperatorNode
// <operator> ::= + | - | * | / | ^ | add | sub | mul | div | pow class OperatorNode extends Node { private String operator; public void parse(Context context) throws Exception { operator = context.currToken(); context.skipToken(operator); } public String toString() { return operator; } public int getValue() throws Exception { // DUMMY return 0; } }
■ OperandNode
// <operand> ::= <number> | <expression> class OperandNode extends Node { private Node node; public void parse(Context context) throws Exception { if (context.currToken().equals("(")) { node = new ExpressionNode(); } else { node = new NumberNode(); } node.parse(context); } public String toString() { return node.toString(); } public int getValue() throws Exception { return node.getValue(); } }
■ NumberNode
// <number> ::= 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 class NumberNode extends Node { private String number; public void parse(Context context) throws Exception { number = context.currToken(); context.skipToken(number); } public String toString() { return number; } public int getValue() throws Exception { int value = 0; try { value = Integer.parseInt(number); } catch (NumberFormatException e) { System.err.println(e); throw e; } return value; } }
L:\>java MyMain (- (+ (/ (+ 6 3) (- 6 2)) (* 3 (^ 2 3))) 1) = 25