Короткое замыкание Префикс Булевы выражения
У меня есть куча логических выражений, написанных в префиксной нотации (также называемой польской нотацией). Вложенные выражения в этом формате очень легко оценить (см. Алгоритм в статье Википедии).
Однако алгоритм, приведенный на странице Википедии, не допускает короткого замыкания (когда он оценивает and f() g()
не пропускает оценку g()
если f()
ложно). Есть ли способ изменить алгоритм для включения короткого замыкания?
2 ответа
Вы можете использовать тот же алгоритм для построения дерева выражений: вместо оценки operand1 operator operand2
создать узел с operand1
а также operand2
как дети, и operator
как родитель.
Когда у вас есть дерево, вы можете оценить его (сверху вниз). Вы можете замкнуть оценку, не оценив одного из детей (например, если левый ребенок оценивает False
и оператор and
).
Вы заметите, что данный алгоритм эквивалентен оценке снизу вверх. Хотя это просто (и экономит память), вы не можете применить короткое замыкание, потому что вы никогда не знаете, должна ли даже оцениваться ветвь, в которой вы находитесь.
Я недавно должен был сделать это и придумал алгоритм, который, кажется, работает:
Разберите выражение, используя шунтирующий ярд, создав ряд постфиксов.
Найдите родительский оператор каждого члена и сохраните смещение.
for term in terms: count = 0 for next in remaining terms: if next type is function: count = count - (argument count - 1) else if next type is operator: count = count - 1 else: count = count + 1 if count is 0: next is term's parent offset = next - term
Оцените обычным способом и проверяйте наличие короткого замыкания после каждой операции. Переходите к сроку после родительского срока, если это применимо.
for term in terms: if term is operator: pop 2 values evaluate (in reverse order) push result value if short-circuit (result is 0 and parent is AND, or result is non-zero and parent is OR): term = term + offset else if term is function: pop arguments evaluate (in reverse order) push result value else: push term value