Balanced parentheses parser Python - python

I am trying to make a balanced parentheses parser by using recursion and produce a tree.
For example, if you pass in '()()' the tree would be constructed like this
step 1
B
|
empty
step 2
B
/ | \ \
( empty ) B
|
empty
step 3
B
/ | \ \
( empty ) B
/ | \ \
( empty ) B
|
empty
Right now, my code "kind of" work for a legit input like '()()', but it is supposed to give me False for something like '())('. It is not returning False. Can I get help with this?
class Node:
def __init__(self, label):
self.label = label
self.leftmostChild = None
self.rightSibling = None
def makeNode0(x):
root = Node(None)
root.label = x
return root
def makeNode1(x, t):
root = makeNode0(x)
root.leftmostChild = t
return root
def makeNode4(x, t1, t2, t3, t4):
root = makeNode1(x, t1)
t1.rightSibling = t2
t2.rightSibling = t3
t3.rightSibling = t4
return root
nextTerminal = "())("
def B(index):
firstB = Node(None)
secondB = Node(None)
if index != len(nextTerminal):
if nextTerminal[index] == '(':
index += 1
firstB = B(index)
if firstB is not False and nextTerminal[index] == ')':
index += 1
secondB = B(index)
if secondB is False:
return False
else:
return makeNode4('B', makeNode0('('), firstB, makeNode0(')'), secondB)
else:
return False
else:
return makeNode1('B', makeNode0('emp'))
b = B(0)

I'm going to outline a second approach here, in the hopes that it provides you with some insight into why your current program isn't working. To be frank, I'm not certain what's going on - I initially thought that each right sibling indicated an additional parenthetical statement, but it seems like the tree's structure is hardcoded, regardless of the parentheses. My suggestion would be to start from the below solution and work your way towards creating these trees.
Keep track of a variable depth.
For every start parenthesis, increment depth by 1.
For every end parenthesis, decrement depth by 1. If depth is negative, we have encountered an end parenthesis too soon -- return false.
After processing all parentheses, check that depth is 0. Otherwise, we had too many start parentheses.

Related

Longest increasing subsequence with binary search

I'm trying to implement some algorithm in python and I need help.
Given some array of integers,
I want to build BTS and find the Longest increasing subsequence.
The idea is to give index to each node(by order of inserting)
Next we want to take all the indices from the left tree and put them in stack
Next we want to check for each index in the above stack if we have in the tree index that is bigger than the current node, if yes we insert it to stack and update the value max which is the number of elements in our stack.
I need help at the point of scanning the tree and insert the elements into a stack.
here is my code so far:
class Node:
def __init__(self, key, index = -1):
self.right = None
self.left = None
self.key = key
self.index = index
def __str__(self):
return "key: %s, index: %s" % (str(self.key), str(self.index))
def insert(root, key, value=-1):
if root is None:
root = Node(key, value)
else:
if key < root.key:
root.left = insert(root.left, key, value)
elif key > root.key:
root.right = insert(root.right, key, value)
else:
pass
return root
def LeftSideIndices(root):
res = []
if root:
res = LeftSideIndices(root.left)
res.append(root.index)
return res
def InOrderWithInsert(root,A):
newStack = []
if root:
for i in range(0, len(A)):
newStack = upInOrder(root.left,A)
if root.index > A[i]:
newStack.append(root.key)
newStack = newStack + upInOrder(root.right, A)
return newStack
Example:
The right stack should be: s=[0,2,8,11]
Some general remarks :
providing a MWE is appreciated.
your code does not define upInOrder so we can't run part of it
nitpick: in the insert function your value parameter is passed to the index parameter of your Node constructor, the naming is confusing.
reformulating your question to make it explicit : "given a Binary Search Tree, find the Longest Increasing Subsequence"
there is a bug in your LeftSideIndices : it returns only indices of left (grand)children instead of the indices of the whole left-half of the tree, example :
bst = insert(insert(insert(None, 2, 0), 0, 1), 1, 2)
# val=2,idx=0
# /
# val=0,idx=1
# \
# val=1,idx=2
print(LeftSideIndices(bst)) # [1, 0]
for reference :
print("value | " + " | ".join(str(value).ljust(2) for value in A) + " |")
print("index | " + " | ".join(str(index).ljust(2) for index in range(len(A))) + " |")
# | value | 4 | 1 | 13 | 7 | 0 | 2 | 8 | 11 | 3 |
# | index | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
as said in the comments, another solution would be to not use a BST at all, and just search the LIS in A (which uses a much more common algorithm). I would even say that using a BST makes it pointlessly hard because the result has nothing to do with the BST structure, it is strictly defined by the insertion order, irregarding the datastructure considered.
There may be multiple different subsequences having the same length (being the longest possible), example :
bst = insert(insert(insert(insert(None, 1, 0), 22, 1), 14, 2), 15, 3)
# val=1,idx=0
# \
# val=22,idx=1
# /
# val=14,idx=2
# \
# val=15,idx=3
# Expected LIS = { (1, 22), (14, 15) }
I read several times your algorithm explanation (slightly reformatted) :
take all the indices from the left tree and put them in stack
check for each index in the stack if we have in the tree index that is bigger than the current node
if yes, insert it to stack and update the value max which is the number of elements in the stack.
I am not sure to understand your algorithm, and I don't think it works.
I am even not sure there is a simple solution to this problem.
The way your indices are scattered accross your tree prevent a node to know which solution(s) from its left and/or right sub-trees are interesting because there is too much holes in the index sequence in a sub-tree, the information at the node level is too much gappy.
Usually for trees algorithms, it is simple to apply some divide and conquer algorithm, but in this case I can't even tell how recursively the root node could tell which is the longest subsequence, given the results of its left and righ subtrees.
But in your case it looks to me extra hard to find how to implement what you want. And I can't convince myself there is actually an algorithm. So I hope you will be able to prove me wrong.

Bad Tree design, Data Structure

I tried making a Tree as a part of my Data Structures course. The code works but is extremely slow, almost double the time that is accepted for the course. I do not have experience with Data Structures and Algorithms but I need to optimize the program. If anyone has any tips, advices, criticism I would greatly appreciate it.
The tree is not necessarily a binary tree.
Here is the code:
import sys
import threading
class Node:
def __init__(self,value):
self.value = value
self.children = []
self.parent = None
def add_child(self,child):
child.parent = self
self.children.append(child)
def compute_height(n, parents):
found = False
indices = []
for i in range(n):
indices.append(i)
for i in range(len(parents)):
currentItem = parents[i]
if currentItem == -1:
root = Node(parents[i])
startingIndex = i
found = True
break
if found == False:
root = Node(parents[0])
startingIndex = 0
return recursion(startingIndex,root,indices,parents)
def recursion(index,toWhomAdd,indexes,values):
children = []
for i in range(len(values)):
if index == values[i]:
children.append(indexes[i])
newNode = Node(indexes[i])
toWhomAdd.add_child(newNode)
recursion(i, newNode, indexes, values)
return toWhomAdd
def checkHeight(node):
if node == '' or node == None or node == []:
return 0
counter = []
for i in node.children:
counter.append(checkHeight(i))
if node.children != []:
mostChildren = max(counter)
else:
mostChildren = 0
return(1 + mostChildren)
def main():
n = int(int(input()))
parents = list(map(int, input().split()))
root = compute_height(n, parents)
print(checkHeight(root))
sys.setrecursionlimit(10**7) # max depth of recursion
threading.stack_size(2**27) # new thread will get stack of such size
threading.Thread(target=main).start()
Edit:
For this input(first number being number of nodes and other numbers the node's values)
5
4 -1 4 1 1
We expect this output(height of the tree)
3
Another example:
Input:
5
-1 0 4 0 3
Output:
4
It looks like the value that is given for a node, is a reference by index of another node (its parent). This is nowhere stated in the question, but if that assumption is right, you don't really need to create the tree with Node instances. Just read the input into a list (which you already do), and you actually have the tree encoded in it.
So for example, the list [4, -1, 4, 1, 1] represents this tree, where the labels are the indices in this list:
1
/ \
4 3
/ \
0 2
The height of this tree — according to the definition given in Wikipedia — would be 2. But apparently the expected result is 3, which is the number of nodes (not edges) on the longest path from the root to a leaf, or — otherwise put — the number of levels in the tree.
The idea to use recursion is correct, but you can do it bottom up (starting at any node), getting the result of the parent recursively, and adding one to 1. Use the principle of dynamic programming by storing the result for each node in a separate list, which I called levels:
def get_num_levels(parents):
levels = [0] * len(parents)
def recur(node):
if levels[node] == 0: # this node's level hasn't been determined yet
parent = parents[node]
levels[node] = 1 if parent == -1 else recur(parent) + 1
return levels[node]
for node in range(len(parents)):
recur(node)
return max(levels)
And the main code could be as you had it:
def main():
n = int(int(input()))
parents = list(map(int, input().split()))
print(get_num_levels(parents))

Generating, traversing and printing binary tree

I generated perfectly balanced binary tree and I want to print it. In the output there are only 0s instead of the data I generated. I think it's because of the line in function printtree that says print(tree.elem), cause in the class self.elem = 0.
How can I connect these two functions generate and printtree?
class BinTree:
def __init__(self):
self.elem = 0
self.left = None
self.right = None
def generate(pbt, N):
if N == 0:
pbt = None
else:
pbt = BinTree()
x = input()
pbt.elem = int(x)
generate(pbt.left, N // 2)
generate(pbt.right, N - N // 2 - 1)
def printtree(tree, h):
if tree is not None:
tree = BinTree()
printtree(tree.right, h+1)
for i in range(1, h):
print(end = "......")
print(tree.elem)
printtree(tree.left, h+1)
Hope somebody can help me. I am a beginner in coding.
For example:
N=6, pbt=pbt, tree=pbt, h=0
input:
1
2
3
4
5
6
and the output:
......5
............6
1
............4
......2
............3
I'd suggest reading up on: https://www.geeksforgeeks.org/tree-traversals-inorder-preorder-and-postorder/
Basically, there are three ways to traverse a binary tree; in-order, post-order and pre-order.
The issue with your print statement is that, you're reassigning the tree that is being passed in, to an empty tree.
if tree is not None:
tree = BinTree()
Right? If tree is not none and has something, lets reassign that to an empty tree.
Traversing a tree is actually a lot more simpler than you'd imagine. I think the complexity comes in just trying to imagine in your head how it all works out, but the truth is that traversing a tree can be done in 3 - 4 lines.

Maximum depth of a binary tree in python

I created a tuple from a binary tree and it looks like this:
tuple = (1,(2,(4,5,6),(7,None,8)),(3,9,(10,11,12)))
The tree structure becomes more clear by applying indentation:
(1,
(2,
(4,
5,
6
),
(7,
None,
8
)
),
(3,
9,
(10,
11,
12
)
)
)
I know how to find the maximum depth of the binary tree using recursive method, but I am trying to find the maximum depth using the tuple I created. Can anyone help me with how to do it?
Recursive method:
a = (1,(2,(4,5,6),(7,None,8)),(3,9,(10,11,12)));
def depth(x):
if(isinstance(x, int) or x == None):
return 1;
else:
dL = depth(x[1]);
dR = depth(x[2]);
return max(dL, dR) + 1;
print(depth(a));
The idea is to determine the depth of a tree by looking at its left and right subtree. If the node does not have subtrees, a depth of 1 is returned. Else it returns max(depth of right, depth of left) + 1
Here is a tricky but rather efficient solution, that will work, provided no elements of your data structure is a string containing '(' or ')'.
I would convert the tuple to a string, and parse it so as to count the depth of the parentheses.
string = str(myTuple)
currentDepth = 0
maxDepth = 0
for c in string:
if c == '(':
currentDepth += 1
elif c == ')':
currentDepth -= 1
maxDepth = max(maxDepth, currentDepth)
It gives the depth in a linear time with regards to the number of characters in the string into which the tuple was converted.
That number should be more or less proportional to the number of elements plus the depth, so you'd have a complexity somewhat equal to O(n + d).
I solve this with level order traversal. If you know level order traversal, this question and https://leetcode.com/problems/binary-tree-right-side-view/ question can be solved with same technique:
from collections import deque
class Solution:
def max_depth(self,root):
if not root:
return 0
level=0
q=deque([root])
while q:
# once we exhaust the for loop, that means we traverse all the nodes in the same level
# so after for loop increase level+=1
for i in range(len(q)):
node=q.popleft()
if node.left:
q.append(node.left)
if node.right:
q.append(node.right)
level+=1
return level
class Node(object):
def __init__(self, x):
self.val = x
self.left = None
self.right = None
class Solution(object):
def maxDepth(self, root):
if not root:
return 0
ldepth = self.maxDepth(root.left)
rdepth = self.maxDepth(root.right)
return max(ldepth, rdepth) + 1

Subtracting branches of a Binary Number Tree in python

So like I have this problem and I have no idea how to do it at all. The problem goes like this:
Define a recursive function called subt_tree() that takes a Binary-Number-Tree and recursively subtracts the value of each right branch from the left branch. So for example, if
tree1 = (25,((10,4),(12,11)))
then subt_tree(tree1) would return
( 25 - ( (10-4) - (12-11) ) ) = ( 25 - ( 6 - 1 ) ) = ( 25 - 5 ) = 20.
So essentially I have to make each tuple into a subtraction problem and then solve.
I've tried this:
def subt_tree(bnt):
"""Takes a bnt and recursively subtracts the value of each right branch from the left branch.
bnt -> number"""
if not isinstance(bnt,tuple):
return 1
else:
return subt_tree(bnt[0]) - subt_tree(bnt[1])
but there must be something wrong in my else statement because no matter what I input it will only return 0 or 1.
Instead of returning 1 why don't you return the value itself? That is after all the base case for your recursion.
i.e.
def subt_tree(bnt):
if not isinstance(bnt,tuple):
return bnt
else:
return subt_tree(bnt[0]) - subt_tree(bnt[1])
If you return 1 you'll only ever get a set of values consisting of 1 being subtracted from each other.

Categories

Resources