As explained in several SO questions, and more abstractly at mathworld, the sequence of Catalan numbers happens to correspond to the number of parenthetical groupings that can be generated for any given number of operators. But I haven't found an algorithm to generate all these groupings.
This binary bracketing algorithm corresponds to the Tamari Lattice and can be described in a number of different ways. The most obvious practical use for this algorithm is to generate all possible expressions by every possible bracketing around binary operators and the numbers they operate on. This can be used to exhaustively test various types of operations on binary trees.
Web searching did reveal one implementation in C# but I think it would take me a while to understand as I don't know C# syntax.
So, what python code generates all the possible groupings of parenthesis around operators (which can thus be used with an actual expression to generate all the possibilities)? Output would look as follows for 2, 3, and 4:
AllBinaryTrees(2)
AllBinaryTrees(3)
AllBinaryTrees(4)
Even better would be code which did something like the following:
AllBinaryTrees("2+3/4")
output:
How about
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)
Sample usage:
for t in allbinarytrees('1+2-3*4/5'):
print(t)
Output:
(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)
The accepted answer only works for single digit numbers, and I will leave it as accepted answer because it illustrates the concept in an easy to read fashion. This modified, messier looking version works for all numbers, not just single digit numbers:
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
Sample usage:
j=0
for t in allbinarytrees('11+22*3/4456'):
j += 1
print j, (t[1:-1])
Output:
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With