回答編集履歴
1
コードを整理してみた
test
CHANGED
@@ -8,168 +8,172 @@
|
|
8
8
|
public class Main {
|
9
9
|
public static void main(String[] args) {
|
10
10
|
String[] testdata = { "1+2.5*-3", "100*50/20", "(20+30)*5", "2(3+5)/4" };
|
11
|
-
for(String fomula : testdata) {
|
11
|
+
for(String formula : testdata) {
|
12
|
-
RPN rpn = new RPN(fomula);
|
12
|
+
RPN rpn = new RPN(formula);
|
13
13
|
System.out.println(rpn + "=" + rpn.calc());
|
14
14
|
}
|
15
15
|
}
|
16
16
|
|
17
17
|
private static class RPN {
|
18
|
-
private e
|
18
|
+
private interface Element {
|
19
|
-
PLS("+",1) {
|
20
|
-
|
19
|
+
void operate(Deque<String> stack);
|
21
|
-
return "" + (Double.parseDouble(a) + Double.parseDouble(b));
|
22
|
-
|
20
|
+
}
|
23
|
-
|
21
|
+
|
24
|
-
|
22
|
+
private static class Value implements Element {
|
25
|
-
|
23
|
+
private final String v;
|
26
|
-
|
24
|
+
Value(String v) {
|
25
|
+
this.v = v;
|
27
|
-
|
26
|
+
}
|
28
|
-
},
|
29
|
-
|
27
|
+
@Override
|
30
|
-
|
28
|
+
public void operate(Deque<String> stack) {
|
31
|
-
|
29
|
+
stack.push(v);
|
32
|
-
|
30
|
+
}
|
33
|
-
},
|
34
|
-
|
31
|
+
@Override
|
35
|
-
|
32
|
+
public String toString() {
|
36
|
-
|
33
|
+
return v;
|
37
|
-
|
34
|
+
}
|
38
|
-
|
35
|
+
}
|
36
|
+
|
37
|
+
private enum Operator implements Element {
|
38
|
+
PLS("+",1) { @Override protected double calc(double a, double b) { return a + b; } },
|
39
|
+
MIN("-",1) { @Override protected double calc(double a, double b) { return a - b; } },
|
40
|
+
MUL("*",2) { @Override protected double calc(double a, double b) { return a * b; } },
|
41
|
+
DIV("/",2) { @Override protected double calc(double a, double b) { return a / b; } },
|
39
42
|
BS("(",0),
|
40
43
|
BE(")",0);
|
41
44
|
|
42
|
-
private final String
|
45
|
+
private final String text;
|
43
46
|
private final int pri;
|
44
|
-
Ope(String
|
47
|
+
Operator(String text, int pri) {
|
45
|
-
this.
|
48
|
+
this.text = text;
|
46
49
|
this.pri = pri;
|
47
50
|
}
|
48
51
|
|
49
|
-
static Ope of(char c) {
|
52
|
+
static Operator of(char c) {
|
50
|
-
for(Ope ope : values()) if(ope.
|
53
|
+
for(Operator ope : values()) if(ope.text.charAt(0) == c) return ope;
|
51
|
-
t
|
54
|
+
return null;
|
52
55
|
}
|
53
56
|
|
57
|
+
@Override
|
58
|
+
public void operate(Deque<String> stack) {
|
59
|
+
double b = Double.parseDouble(stack.pop());
|
60
|
+
double a = Double.parseDouble(stack.pop());
|
61
|
+
stack.push("" + calc(a, b));
|
62
|
+
}
|
63
|
+
|
54
|
-
|
64
|
+
protected double calc(double a, double b) {
|
55
65
|
throw new UnsupportedOperationException();
|
56
66
|
}
|
57
67
|
|
58
68
|
@Override
|
59
69
|
public String toString() {
|
60
|
-
return
|
70
|
+
return text;
|
61
71
|
}
|
62
72
|
}
|
63
73
|
|
64
74
|
private static class Translator {
|
75
|
+
private static class Source {
|
76
|
+
private static Pattern NUM_PATTERN = Pattern.compile("-?\\d+(:?\\.\\d+)?");
|
77
|
+
|
78
|
+
private final String formula;
|
79
|
+
private int index;
|
80
|
+
|
81
|
+
Source(String formula) {
|
82
|
+
this.formula = formula;
|
83
|
+
}
|
84
|
+
|
85
|
+
boolean isEnd() { return index >= formula.length(); }
|
86
|
+
char getChar() { return formula.charAt(index); }
|
87
|
+
Operator nextOperator() {
|
88
|
+
Operator op = Operator.of(formula.charAt(index++));
|
89
|
+
if(op == null) throw new IllegalArgumentException("Operator Error: index=" + index);
|
90
|
+
return op;
|
91
|
+
}
|
92
|
+
Value nextNumber() {
|
93
|
+
Matcher m = NUM_PATTERN.matcher(formula.substring(index));
|
94
|
+
if(!m.find() || m.start() != 0) throw new IllegalArgumentException("Number Error: index=" + index);
|
95
|
+
index += m.group().length();
|
96
|
+
return new Value(m.group());
|
97
|
+
}
|
98
|
+
}
|
99
|
+
|
100
|
+
private static class Destination {
|
101
|
+
private Deque<Operator> stack = new ArrayDeque<>();
|
102
|
+
private List<Element> list = new ArrayList<>();
|
103
|
+
|
104
|
+
void put(Operator op) {
|
105
|
+
if(op == Operator.BE) {
|
106
|
+
while(!stack.isEmpty() && (op=stack.pop()) != Operator.BS) list.add(op);
|
107
|
+
if(op != Operator.BS) throw new IllegalStateException("Formula Error: Unmatched parentheses.");
|
108
|
+
return;
|
109
|
+
}
|
110
|
+
if(op != Operator.BS) {
|
111
|
+
while(!stack.isEmpty() && stack.peek().pri >= op.pri) list.add(stack.pop());
|
112
|
+
}
|
113
|
+
stack.push(op);
|
114
|
+
}
|
115
|
+
void put(Value v) {
|
116
|
+
list.add(v);
|
117
|
+
}
|
118
|
+
List<Element> complete() {
|
119
|
+
while(!stack.isEmpty()) list.add(stack.pop());
|
120
|
+
return new ArrayList<>(list);
|
121
|
+
}
|
122
|
+
}
|
123
|
+
|
65
124
|
private enum Mode {
|
66
125
|
NUM {
|
67
|
-
Pattern numPatten = Pattern.compile("-?\\d+(:?\\.\\d+)?");
|
68
|
-
Mode translate(
|
126
|
+
Mode translate(Source src, Destination dst) {
|
69
|
-
if(
|
127
|
+
if(src.getChar() == '(') {
|
70
|
-
|
128
|
+
dst.put(src.nextOperator());
|
71
|
-
} else {
|
72
|
-
Matcher m = numPatten.matcher(translator.substring());
|
73
|
-
if(m.find() && m.start() == 0) {
|
74
|
-
translator.putValue(m.group(), m.group().length()-1);
|
75
|
-
} else {
|
76
|
-
throw new IllegalArgumentException("fomula Error: index=" + translator.index);
|
77
|
-
}
|
78
|
-
return
|
129
|
+
return this;
|
79
130
|
}
|
131
|
+
dst.put(src.nextNumber());
|
80
|
-
return
|
132
|
+
return OP;
|
81
133
|
}
|
82
134
|
},
|
83
135
|
OP {
|
84
|
-
Mode translate(
|
136
|
+
Mode translate(Source src, Destination dst) {
|
85
|
-
|
137
|
+
Operator op = src.nextOperator();
|
86
|
-
if(c == '+' || c == '-' || c == '*' || c == '/') {
|
87
|
-
translator.putOpe(Ope.of(c));
|
88
|
-
return NUM;
|
89
|
-
}
|
90
|
-
if(
|
138
|
+
if(op == Operator.BE) {
|
91
|
-
translator.putOpe(Ope.of('*'));
|
92
|
-
translator.putOpe(Ope.of('('));
|
93
|
-
|
139
|
+
dst.put(op);
|
94
|
-
}
|
95
|
-
if(c == ')') {
|
96
|
-
translator.putOpe(Ope.of(')'));
|
97
140
|
return this;
|
98
141
|
}
|
99
|
-
|
142
|
+
if(op == Operator.BS) dst.put(Operator.MUL);
|
143
|
+
dst.put(op);
|
144
|
+
return NUM;
|
100
145
|
}
|
101
146
|
};
|
102
147
|
|
103
|
-
abstract Mode translate(
|
148
|
+
abstract Mode translate(Source src, Destination dst);
|
104
149
|
}
|
105
150
|
|
106
|
-
private final String fomula;
|
107
|
-
private int index;
|
108
|
-
|
109
|
-
private Deque<Ope> opeList = new ArrayDeque<>();
|
110
|
-
private List<Object> list = new ArrayList<>();
|
111
|
-
|
112
|
-
Translator(String fomula) {
|
113
|
-
this.fomula = fomula;
|
114
|
-
}
|
115
|
-
|
116
|
-
List<
|
151
|
+
static List<Element> translate(String formula) {
|
117
152
|
Mode mode = Mode.NUM;
|
118
|
-
o
|
153
|
+
Source src = new Source(formula);
|
119
|
-
list.clear();
|
120
|
-
|
154
|
+
Destination dst = new Destination();
|
121
|
-
|
122
|
-
while(!
|
155
|
+
while(!src.isEnd()) mode = mode.translate(src, dst);
|
123
|
-
return list;
|
124
|
-
}
|
125
|
-
|
126
|
-
private char target() {
|
127
|
-
return
|
156
|
+
return dst.complete();
|
128
|
-
}
|
129
|
-
private String substring() {
|
130
|
-
return fomula.substring(index);
|
131
|
-
}
|
132
|
-
private void putOpe(Ope ope) {
|
133
|
-
if(ope == Ope.BE) {
|
134
|
-
while(!opeList.isEmpty() && (ope=opeList.pop()) != Ope.BS) list.add(ope);
|
135
|
-
return;
|
136
|
-
}
|
137
|
-
if(ope != Ope.BS) {
|
138
|
-
while(!opeList.isEmpty() && opeList.peek().pri >= ope.pri) list.add(opeList.pop());
|
139
|
-
}
|
140
|
-
opeList.push(ope);
|
141
|
-
}
|
142
|
-
private void putValue(String v, int di) {
|
143
|
-
index += di;
|
144
|
-
list.add(v);
|
145
157
|
}
|
146
158
|
}
|
147
159
|
|
148
|
-
private final String fomula;
|
160
|
+
private final String formula;
|
149
|
-
private List<
|
161
|
+
private List<Element> list;
|
150
162
|
|
151
|
-
RPN(String fomula) {
|
163
|
+
RPN(String formula) {
|
152
|
-
this.fomula = fomula;
|
164
|
+
this.formula = formula;
|
153
|
-
list =
|
165
|
+
list = Translator.translate(formula);
|
154
166
|
}
|
155
167
|
|
156
168
|
String calc() {
|
157
169
|
Deque<String> stack = new ArrayDeque<>();
|
158
|
-
for(
|
170
|
+
for(Element elm : list) elm.operate(stack);
|
159
|
-
if(obj instanceof Ope) {
|
160
|
-
String b = stack.pop();
|
161
|
-
String a = stack.pop();
|
162
|
-
stack.push(((Ope)obj).calc(a, b));
|
163
|
-
} else /*if(obj instanceof String)*/ {
|
164
|
-
stack.push((String)obj);
|
165
|
-
}
|
166
|
-
}
|
167
171
|
return stack.pop();
|
168
172
|
}
|
169
173
|
|
170
174
|
@Override
|
171
175
|
public String toString() {
|
172
|
-
return fomula + "=" + list;
|
176
|
+
return formula + "=" + list;
|
173
177
|
}
|
174
178
|
}
|
175
179
|
}
|