質問編集履歴

4

正規表現の誤りを修正

2017/09/25 08:23

投稿

workr
workr

スコア158

test CHANGED
File without changes
test CHANGED
@@ -244,7 +244,7 @@
244
244
 
245
245
  $expression = preg_replace('/\s/', '', $expression);
246
246
 
247
- preg_match_all('/[0-9a-zA-Z-_]+|&&|\|\||\(\)/', $expression, $matches);
247
+ preg_match_all('/[0-9a-zA-Z-_]+|&&|\|\||\(|\)/', $expression, $matches);
248
248
 
249
249
 
250
250
 

3

引数と返り値を変更

2017/09/25 08:23

投稿

workr
workr

スコア158

test CHANGED
File without changes
test CHANGED
@@ -182,9 +182,13 @@
182
182
 
183
183
  function checkFlags($expression, $flags){
184
184
 
185
- $postfix = convertToPostfix($expression, $flags);
185
+ $postfix = convertToPostfix($expression);
186
+
187
+
188
+
186
-
189
+ $postfix = strtr($postfix, $flags);
187
-
190
+
191
+
188
192
 
189
193
  $parts = preg_split('/\s/', $postfix, -1, PREG_SPLIT_NO_EMPTY);
190
194
 
@@ -200,9 +204,9 @@
200
204
 
201
205
  } else {
202
206
 
203
- $b = (int)array_pop($stack);
207
+ $b = (float)array_pop($stack);
204
-
208
+
205
- $a = (int)array_pop($stack);
209
+ $a = (float)array_pop($stack);
206
210
 
207
211
 
208
212
 
@@ -236,22 +240,16 @@
236
240
 
237
241
 
238
242
 
239
- function convertToPostfix($expression, $flags) {
243
+ function convertToPostfix($expression) {
240
244
 
241
245
  $expression = preg_replace('/\s/', '', $expression);
242
246
 
247
+ preg_match_all('/[0-9a-zA-Z-_]+|&&|\|\||\(\)/', $expression, $matches);
248
+
249
+
250
+
243
251
  if(substr_count($expression, '(') !== substr_count($expression, ')')) return false;
244
252
 
245
-
246
-
247
- $expression = strtr($expression, $flags);
248
-
249
- preg_match_all('/[0-9]+|&&|\|\||\(\)/', $expression, $matches);
250
-
251
-
252
-
253
- if(substr_count($expression, '(') !== substr_count($expression, ')')) return false;
254
-
255
253
 
256
254
 
257
255
  $parts = $matches[0];
@@ -270,59 +268,59 @@
270
268
 
271
269
  foreach ($parts as $part) {
272
270
 
271
+ if( $part == '&&' || $part == '||' ) {
272
+
273
- if (is_numeric($part)) {
273
+ if (!empty($stack)) {
274
+
275
+ while (true) {
276
+
277
+ $end = end($stack);
278
+
279
+ if ($end && $priorities[$part] <= $priorities[$end]) {
280
+
281
+ $output []= array_pop($stack);
282
+
283
+ } else {
284
+
285
+ break;
286
+
287
+ }
288
+
289
+ }
290
+
291
+ }
292
+
293
+ $stack[] = $part;
294
+
295
+ } elseif ($part == '(') {
296
+
297
+ $stack[] = $part;
298
+
299
+ } elseif ($part == ')') {
300
+
301
+ while (count($stack) > 0) {
302
+
303
+ $end = end($stack);
304
+
305
+ if ($end == '(') {
306
+
307
+ array_pop($stack);
308
+
309
+ break;
310
+
311
+ } else {
312
+
313
+ $output[] = array_pop($stack);
314
+
315
+ }
316
+
317
+ }
318
+
319
+ } else {
274
320
 
275
321
  $output[] = $part;
276
322
 
277
- } elseif ($part == '(') {
278
-
279
- $stack[] = $part;
280
-
281
- } elseif ($part == ')') {
282
-
283
- while (count($stack) > 0) {
284
-
285
- $end = end($stack);
286
-
287
- if ($end == '(') {
288
-
289
- array_pop($stack);
290
-
291
- break;
292
-
293
- } else {
294
-
295
- $output[] = array_pop($stack);
296
-
297
- }
323
+ }
298
-
299
- }
300
-
301
- } else {
302
-
303
- if (!empty($stack)) {
304
-
305
- while (true) {
306
-
307
- $end = end($stack);
308
-
309
- if ($end && $priorities[$part] <= $priorities[$end]) {
310
-
311
- $output []= array_pop($stack);
312
-
313
- } else {
314
-
315
- break;
316
-
317
- }
318
-
319
- }
320
-
321
- }
322
-
323
- $stack[] = $part;
324
-
325
- }
326
324
 
327
325
  }
328
326
 

2

floatをintに変更

2017/09/14 06:04

投稿

workr
workr

スコア158

test CHANGED
File without changes
test CHANGED
@@ -200,9 +200,9 @@
200
200
 
201
201
  } else {
202
202
 
203
- $b = (float)array_pop($stack);
203
+ $b = (int)array_pop($stack);
204
-
204
+
205
- $a = (float)array_pop($stack);
205
+ $a = (int)array_pop($stack);
206
206
 
207
207
 
208
208
 

1

解決方法を追記

2017/09/14 05:35

投稿

workr
workr

スコア158

test CHANGED
File without changes
test CHANGED
@@ -129,3 +129,215 @@
129
129
  おかしなやり方をしている部分もあると思いますし、根本的に間違っている場合は全く別のやり方でも構いません。
130
130
 
131
131
  よろしくお願いします。
132
+
133
+
134
+
135
+
136
+
137
+
138
+
139
+ ### 追記
140
+
141
+
142
+
143
+ 2017-09-14
144
+
145
+
146
+
147
+ shimitei様にコメントで教えていただいた逆ポーランド記法を使いソース全体を作り直しました。
148
+
149
+ ひとまず正しく動作できているようなので掲載しておきます。改善点や修正点がありましたらコメントか編集をお願い致します。
150
+
151
+
152
+
153
+ ```PHP
154
+
155
+ <?php
156
+
157
+ $flags = [
158
+
159
+ 'flag1' => 1,
160
+
161
+ 'flag2' => 0,
162
+
163
+ 'flag3' => 0,
164
+
165
+ 'flag4' => 1,
166
+
167
+ 'flag5' => 1
168
+
169
+ ];
170
+
171
+
172
+
173
+ // 「&&」は AND, 「||」 は OR を表す
174
+
175
+ $expression = 'flag1 && (flag2 || flag3) || (flag4 && flag5)';
176
+
177
+
178
+
179
+ var_dump(checkFlags( $expression, $flags ) );
180
+
181
+
182
+
183
+ function checkFlags($expression, $flags){
184
+
185
+ $postfix = convertToPostfix($expression, $flags);
186
+
187
+
188
+
189
+ $parts = preg_split('/\s/', $postfix, -1, PREG_SPLIT_NO_EMPTY);
190
+
191
+ $stack = [];
192
+
193
+
194
+
195
+ foreach ($parts as $part) {
196
+
197
+ if (is_numeric($part)) {
198
+
199
+ $stack[] = $part;
200
+
201
+ } else {
202
+
203
+ $b = (float)array_pop($stack);
204
+
205
+ $a = (float)array_pop($stack);
206
+
207
+
208
+
209
+ switch ($part) {
210
+
211
+ case "&&":
212
+
213
+ $x = $a && $b;
214
+
215
+ array_push($stack, $x);
216
+
217
+ break;
218
+
219
+ case "||":
220
+
221
+ $x = $a || $b;
222
+
223
+ array_push($stack, $x);
224
+
225
+ }
226
+
227
+ }
228
+
229
+ }
230
+
231
+
232
+
233
+ return (bool)$stack[0];
234
+
235
+ }
236
+
237
+
238
+
239
+ function convertToPostfix($expression, $flags) {
240
+
241
+ $expression = preg_replace('/\s/', '', $expression);
242
+
243
+ if(substr_count($expression, '(') !== substr_count($expression, ')')) return false;
244
+
245
+
246
+
247
+ $expression = strtr($expression, $flags);
248
+
249
+ preg_match_all('/[0-9]+|&&|\|\||\(\)/', $expression, $matches);
250
+
251
+
252
+
253
+ if(substr_count($expression, '(') !== substr_count($expression, ')')) return false;
254
+
255
+
256
+
257
+ $parts = $matches[0];
258
+
259
+
260
+
261
+ $stack = [];
262
+
263
+ $output = [];
264
+
265
+
266
+
267
+ $priorities = [ '&&' => 2, '||' => 2, '(' => 1, ')' => 1 ];
268
+
269
+
270
+
271
+ foreach ($parts as $part) {
272
+
273
+ if (is_numeric($part)) {
274
+
275
+ $output[] = $part;
276
+
277
+ } elseif ($part == '(') {
278
+
279
+ $stack[] = $part;
280
+
281
+ } elseif ($part == ')') {
282
+
283
+ while (count($stack) > 0) {
284
+
285
+ $end = end($stack);
286
+
287
+ if ($end == '(') {
288
+
289
+ array_pop($stack);
290
+
291
+ break;
292
+
293
+ } else {
294
+
295
+ $output[] = array_pop($stack);
296
+
297
+ }
298
+
299
+ }
300
+
301
+ } else {
302
+
303
+ if (!empty($stack)) {
304
+
305
+ while (true) {
306
+
307
+ $end = end($stack);
308
+
309
+ if ($end && $priorities[$part] <= $priorities[$end]) {
310
+
311
+ $output []= array_pop($stack);
312
+
313
+ } else {
314
+
315
+ break;
316
+
317
+ }
318
+
319
+ }
320
+
321
+ }
322
+
323
+ $stack[] = $part;
324
+
325
+ }
326
+
327
+ }
328
+
329
+
330
+
331
+ while (count($stack) > 0) {
332
+
333
+ $output[] = array_pop($stack);
334
+
335
+ }
336
+
337
+
338
+
339
+ return implode(' ', $output);
340
+
341
+ }
342
+
343
+ ```