回答編集履歴

1

コードを整理してみた

2023/02/06 19:46

投稿

jimbe
jimbe

スコア13168

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 enum Ope {
18
+ private interface Element {
19
- PLS("+",1) {
20
- String calc(String a, String b) {
19
+ void operate(Deque<String> stack);
21
- return "" + (Double.parseDouble(a) + Double.parseDouble(b));
22
- }
20
+ }
23
- },
21
+
24
- MIN("-",1) {
22
+ private static class Value implements Element {
25
- String calc(String a, String b) {
23
+ private final String v;
26
- return "" + (Double.parseDouble(a) - Double.parseDouble(b));
24
+ Value(String v) {
25
+ this.v = v;
27
- }
26
+ }
28
- },
29
- MUL("*",2) {
27
+ @Override
30
- String calc(String a, String b) {
28
+ public void operate(Deque<String> stack) {
31
- return "" + (Double.parseDouble(a) * Double.parseDouble(b));
29
+ stack.push(v);
32
- }
30
+ }
33
- },
34
- DIV("/",2) {
31
+ @Override
35
- String calc(String a, String b) {
32
+ public String toString() {
36
- return "" + (Double.parseDouble(a) / Double.parseDouble(b));
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 s;
45
+ private final String text;
43
46
  private final int pri;
44
- Ope(String s, int pri) {
47
+ Operator(String text, int pri) {
45
- this.s = s;
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.s.charAt(0) == c) return ope;
53
+ for(Operator ope : values()) if(ope.text.charAt(0) == c) return ope;
51
- throw new IllegalArgumentException("Ope Error: c=" + c);
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
- String calc(String a, String b) {
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 s;
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(Translator translator) {
126
+ Mode translate(Source src, Destination dst) {
69
- if(translator.target() == '(') {
127
+ if(src.getChar() == '(') {
70
- translator.putOpe(Ope.of(translator.target()));
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 OP;
129
+ return this;
79
130
  }
131
+ dst.put(src.nextNumber());
80
- return this;
132
+ return OP;
81
133
  }
82
134
  },
83
135
  OP {
84
- Mode translate(Translator translator) {
136
+ Mode translate(Source src, Destination dst) {
85
- char c = translator.target();
137
+ Operator op = src.nextOperator();
86
- if(c == '+' || c == '-' || c == '*' || c == '/') {
87
- translator.putOpe(Ope.of(c));
88
- return NUM;
89
- }
90
- if(c == '(') {
138
+ if(op == Operator.BE) {
91
- translator.putOpe(Ope.of('*'));
92
- translator.putOpe(Ope.of('('));
93
- return NUM;
139
+ dst.put(op);
94
- }
95
- if(c == ')') {
96
- translator.putOpe(Ope.of(')'));
97
140
  return this;
98
141
  }
99
- throw new IllegalArgumentException("fomula Error: index=" + translator.index);
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(Translator translator);
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<Object> translate() {
151
+ static List<Element> translate(String formula) {
117
152
  Mode mode = Mode.NUM;
118
- opeList.clear();
153
+ Source src = new Source(formula);
119
- list.clear();
120
- for(index=0; index<fomula.length(); index++) mode = mode.translate(this);
154
+ Destination dst = new Destination();
121
-
122
- while(!opeList.isEmpty()) list.add(opeList.pop());
155
+ while(!src.isEnd()) mode = mode.translate(src, dst);
123
- return list;
124
- }
125
-
126
- private char target() {
127
- return fomula.charAt(index);
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<Object> 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 = new Translator(fomula).translate();
165
+ list = Translator.translate(formula);
154
166
  }
155
167
 
156
168
  String calc() {
157
169
  Deque<String> stack = new ArrayDeque<>();
158
- for(Object obj : list) {
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
  }