Какой код python генерирует все возможные группировки (деревья) для двоичных операторов
Как объясняется в нескольких Так вопросов, и более абстрактно на mathworld, последовательность каталонских чисел соответствует числу парентетических группировок, которые могут быть сгенерированы для любого заданного числа операторов. Но я не нашел алгоритма для генерации всех этих группировок.
этот алгоритм бинарного брекетинга соответствует Тамари Решетки и может быть описан несколькими различными способами. Наиболее очевидные практические этот алгоритм используется для генерации всех возможных выражений с помощью всех возможных скобок вокруг двоичных операторов и чисел, с которыми они работают. Это можно использовать для исчерпывающего тестирования различных типов операций над двоичными деревьями.
веб-поиск показал одна реализация в C# но я думаю, что мне потребуется некоторое время, чтобы понять, поскольку я не знаю синтаксиса C#.
Итак, какой код python генерирует все возможные группировки скобок вокруг операторы (которые, таким образом, могут использоваться с фактическим выражением для генерации всех возможностей)? Вывод будет выглядеть следующим образом для 2, 3, и лучше бы был код, который делал что-то вроде следующего:
AllBinaryTrees("2+3/4")
выход:
- 2+(3/4)
- (2+3)/4
2 ответов
как о
def allbinarytrees(s):
if len(s) == 1:
yield s
else:
for i in range(1, len(s), 2):
for l in allbinarytrees(s[:i]):
for r in allbinarytrees(s[i+1:]):
yield '({}{}{})'.format(l, s[i], r)
пример использования:
for t in allbinarytrees('1+2-3*4/5'):
print(t)
выход:
(1+(2-(3*(4/5))))
(1+(2-((3*4)/5)))
(1+((2-3)*(4/5)))
(1+((2-(3*4))/5))
(1+(((2-3)*4)/5))
((1+2)-(3*(4/5)))
((1+2)-((3*4)/5))
((1+(2-3))*(4/5))
(((1+2)-3)*(4/5))
((1+(2-(3*4)))/5)
((1+((2-3)*4))/5)
(((1+2)-(3*4))/5)
(((1+(2-3))*4)/5)
((((1+2)-3)*4)/5)
принятый ответ работает только для однозначных чисел, и я оставлю его как принятый ответ, потому что он иллюстрирует концепцию легко читаемым способом. Эта модифицированная, более беспорядочная версия работает для всех чисел, а не только для однозначных чисел:
def allbinarytrees(s):
if s.isdigit():
yield s
else:
i = 0
while i < len(s)-1:
while i < len(s) and s[i].isdigit():
i += 1
if i < len(s) - 1:
for left in allbinarytrees(s[:i]):
for right in allbinarytrees(s[i+1:]):
yield '({}{}{})'.format(left, s[i], right)
i += 1
пример использования:
j=0
for t in allbinarytrees('11+22*3/4456'):
j += 1
print j, (t[1:-1])
выход:
1 11+(22*(3/4456))
2 11+((22*3)/4456)
3 (11+22)*(3/4456)
4 (11+(22*3))/4456
5 ((11+22)*3)/4456