Regexp проблема, связанная с калькулятором обратной польской
Я пытаюсь использовать регулярное выражение для решения проблемы обратного польского калькулятора, но у меня возникают проблемы с преобразованием математических выражений в обычную форму.
Я написал:
puts '35 29 1 - 5 + *'.gsub(/(\d*) (\d*) (\W)/, '(\1\3\2)')
который печатает:
35 (29-1)(+5) *
ожидаемый
(35*((29-1)+5))
но я получаю другой результат. Что я делаю неправильно?
1 ответ
Я предполагаю, что вы имели в виду, что вы пытались
puts '35 29 1 - 5 + *'.gsub(/(\d*) (\d*) (\W)/, '(\1\3\2)')
^ ^
В любом случае, вы должны использовать квантификатор +
вместо *
, так как в противном случае вы будете соответствовать пустой строке для \d*
как один из ваших захватов, следовательно, (+5)
:
/(\d+) (\d+) (\W)/
Я бы далее расширил / ограничил выражение чем-то вроде:
/([\d+*\/()-]+)\s+([\d+*\/()-]+)\s+([+*\/-])/
| | | | |
| | | | Valid operators, +, -, *, and /.
| | | |
| | | Whitespace.
| | |
| | Arbitrary atom, e.g. "35", "(29-1)", "((29-1)+5)".
| |
| Whitepsace.
|
Arbitrary atom, e.g. "35", "(29-1)", "((29-1)+5)".
... и вместо того, чтобы использовать gsub
использовать sub
в while
Цикл, который завершается, когда обнаруживает, что больше нет замен. Это очень важно, потому что в противном случае вы нарушите порядок операций. Например, взгляните на эту демонстрацию Rubular. Вы можете увидеть это, используя gsub
Вы могли бы потенциально заменить вторую триаду атомов, "5 + *", когда действительно вторая итерация должна заменить "более раннюю" триаду после замены первой триады!
ВНИМАНИЕ: -
(минус) символ должен появляться первым или последним в классе символов, так как в противном случае он будет указывать диапазон! (Спасибо @JoshuaCheek.)