how to fix the count function - python

class TN:
def __init__(self,value,left=None,right=None):
self.value = value
self.left = left
self.right = right
def list_to_tree(alist):
if alist == None:
return None
else:
return TN(alist[0],list_to_tree(alist[1]),list_to_tree(alist[2]))
def str_tree(atree,indent_char ='.',indent_delta=2):
def str_tree_1(indent,atree):
if atree == None:
return ''
else:
answer = ''
answer += str_tree_1(indent+indent_delta,atree.right)
answer += indent*indent_char+str(atree.value)+'\n'
answer += str_tree_1(indent+indent_delta,atree.left)
return answer
return str_tree_1(0,atree)
def count(t,value):
nodes = []
num = 0
nodes.append(t)
while len(nodes) > 0:
if nodes[0] == value:
num += 1
next = nodes.pop(0)
count(next,value)
return num
I need to write a recursive function count (other three functions cannot be changed); it is passed balanced binary tree and a value as arguments. It returns the number of times the values is in the tree. In the binary tree below, count(tree,1) returns 1, count(tree,2) returns 2, count(tree,3) returns 4
..1
....3
3
....3
..2
......2
....3
I called the following functions
tree = list_to_tree([3, [2, None, [3, None, None]], [1, [3, None, None], None]])
print('\nfor tree = \n',str_tree(tree))
for i in irange(1,3):
print('count(tree,'+str(i)+') = ', count(tree,i))
but it shows the error that "RecursionError: maximum recursion depth exceeded in comparison"
can someone help me to fix the count function? Thanks in advance.

If you look carefully at your code you'll see that you set up an empty nodes list, fill it with t, so the while loop is always entered you'll always pop t into next and always call the function with precisely the same parameters. That is of course an infinite recursion.
Here is one simple way of setting it up correctly:
def count(tree, number):
if tree is None:
return 0
else:
return (number == tree.value) + count(tree.left, number) \
+ count(tree.right, number)

Another way to go about it is using transversal, in a typical tree there is a root and a node subclass. Your tree is missing that structure so it looks a bit weird. To use transversal I'm using a global var to keep track of the counter.
class TN:
def __init__(self,value,left=None,right=None):
self.value = value
self.left = left
self.right = right
def list_to_tree(alist):
if alist == None:
return None
else:
return TN(alist[0],list_to_tree(alist[1]),list_to_tree(alist[2]))
def str_tree(atree,indent_char ='.',indent_delta=2):
def str_tree_1(indent,atree):
if atree == None:
return ''
else:
answer = ''
answer += str_tree_1(indent+indent_delta,atree.right)
answer += indent*indent_char+str(atree.value)+'\n'
answer += str_tree_1(indent+indent_delta,atree.left)
return answer
return str_tree_1(0,atree)
NUM = 0
def count(t,value):
global NUM
NUM = 0
if t != None:
if t.left == None and t.right == None:
if t.value == value:
return 1
else:
return 0
else:
_count(t, value)
return NUM
def _count(t, value):
if t.left != None:
_count(t.left, value)
if t.value == value:
global NUM
NUM += 1
if t.right != None:
_count(t.right, value)
tree = list_to_tree([3, [2, None, [3, None, None]], [1, [3, None, None], None]])
print(str_tree(tree))
print("count 1", count(tree, 1))
print("count 2", count(tree, 2))
print("count 3", count(tree, 3))

Related

Create a linked list function without creating another class

I am working on some practice exercises with linked lists and I got stuck with one function.
My program should create a Node class, take user input with create() function (number n and then takes in n number of elements), and has a function printLinkedList(p) to print it out. So far this works well but then I should create another function where I am going to be deleting the max element (if it occurs more than once, delete the first occurrence).
I found a function findMaxElement(p) that looks for the max, however, it doesn't work along my code (for example I get AttributeError: 'Node' object has no attribute 'head' error)
class Node:
def __init__(self, x = None):
self.data = x
self.next = None
def create():
n = int(input())
if n == 0:
return None
s = input().split()
p = Node(int(s[0]))
k = p
for i in range(1, n):
t = Node(int(s[i]))
k.next = t
k = t
return p
def printLinkedList(p):
if p == None:
print('Empty')
return
s = p
while s != None:
print(s.data, end = " ")
s = s.next
print()
def findMaxElement(p):
current = p.head
#Initializing max to initial node info
maximum = p.head.data
if(p.head == None):
print("List is empty")
else:
while(True):
#If current node's info is greater than max
#Then replace value of max with current node's info
if(maximum < current.info):
maximum = current.info
current= current.next
if(current == p.head):
break
return "Maximum value node in the list: "+ str(maximum)
#Driver code
a = create()
printLinkedList(a)
Input:
6
1 7 4 2 6 7
Expected result:
1 7 4 2 6 7
1 4 2 6 7
You could just define a findMaxElement() that traverses the linked-list in the same way that the printLinkedList() function is doing it (and finds the maximum value while doing so):
def findMaxElement(p):
if p == None:
return 'Empty List!'
current = p
maximum = p.data
while current != None: # Not end of list.
if current.data > maximum:
maximum = current.data
current = current.next
return "Maximum value node in the list: " + str(maximum)

Python implementation of Determining DNA Health algorithm from HackerRank

I am trying to solve Determining DNA Health challenge from Hackerrank using python. (I have to add I am somewhat new to python 3. Still learning the language)
My solution fails for test cases 7, 8 and 9 with a message reading "Wrong Answer".
When I run the following code locally, I can confirm that for these test cases my implementation produces the expected output.
I am wondering what would be the problem.
I am a bit puzzled at the moment. Is there a problem with my implementation? If so how come it produces correct answers for 28 test cases but fails on these 3? Or is it a misleading/confusing result message from Hacker Rank, as I happen to know that people find these 3 test cases (7, 8 and 9) problematic from what I learnt from reading discussions.
Any help would be highly appreciated.
Here is the code I wrote:
from bisect import bisect_left
from bisect import bisect_right
import sys
from unittest.mock import right
class TrieNode(object):
def __init__(self):
self.subnodes = {}
self.isTerminal = False
self.indexList = []
self.healthList = []
def addSubnode(self, aChar):
if (self.subnodes.get(aChar)):
return self.subnodes[aChar]
else:
newNode = TrieNode()
self.subnodes[aChar] = newNode
return newNode
def addIndexAndValue(self, index, health):
self.isTerminal = True
self.indexList.append(index)
lastHealth = 0
healthLength = len(self.healthList)
if (healthLength>0):
lastHealth = self.healthList[healthLength-1]
self.healthList.append(lastHealth + health)
def getSubnodeFor(self, aChar):
return self.subnodes.get(aChar)
def getValueForIndexes(self, startIndex, endIndex):
listSize = len(self.indexList)
if listSize < 1:
return 0
elif listSize == 1:
if startIndex <= self.indexList[0] and endIndex >= self.indexList[0]:
return self.healthList[0]
else:
return 0
else: # listSize > 1
rightInd = bisect_left(self.indexList, endIndex)
if rightInd < listSize and endIndex < self.indexList[0]:
return 0
big = 0
if rightInd >= listSize:
big = self.healthList[listSize - 1]
else:
if endIndex >= self.indexList[rightInd]:
big = self.healthList[rightInd]
else:
big = self.healthList[rightInd-1]
leftInd = bisect_left(self.indexList, startIndex)
small = 0
if leftInd >= listSize:
return 0
else:
if startIndex <= self.indexList[leftInd]:
if (leftInd > 0):
small = self.healthList[leftInd - 1]
else:
small = 0
else:
small = self.healthList[leftInd]
return big - small
class Trie(object):
def __init__(self):
self.root = TrieNode()
def getRoot(self):
return self.root
def createTrie(self, genes, healths):
for i in range(len(genes)):
node = self.root
for c in genes[i]:
node = node.addSubnode(c)
node.addIndexAndValue(i, healths[i])
def calculateHealth(trie, d, first, last):
total = 0
dLength = len(d)
for i in range(0, dLength):
node = trie.getRoot()
for j in range(i, dLength):
node = node.getSubnodeFor(d[j])
if node != None:
if node.isTerminal:
val = node.getValueForIndexes(first, last)
total = total + val
else:
break
return total
def readFromFile(aFileName):
inputArr = None
with open('../hackerRank/src/' + aFileName, encoding='utf-8') as aFile:
inputArr = aFile.read().splitlines()
return inputArr
def runFor(fileName, minimumValue, maximumValue):
inp = readFromFile(fileName)
n = inp[0]
genes = inp[1].rstrip().split()
healths = list(map(int, inp[2].rstrip().split()))
trie = Trie()
trie.createTrie(genes, healths)
s = int(inp[3])
minVal = sys.maxsize
maxVal = -1
for fItr in range(s):
line = inp[fItr+4].split()
first = int(line[0])
last = int(line[1])
d = line[2]
val = calculateHealth(trie, d, first, last)
if val < minVal:
minVal = val
if val > maxVal:
maxVal = val
print (minVal,maxVal)
assert minimumValue == minVal
assert maximumValue == maxVal
# TextX.txt 's are simple text files, which hold test data for regarding test case
# following the file name are real expected numbers for each relevant test case
# I got those from hacker rank
runFor('Test2.txt', 15806635, 20688978289)
runFor('Test7.txt', 0, 7353994)
runFor('Test8.txt', 0, 8652768)
runFor('Test9.txt', 0, 9920592)
runFor('Test33.txt', 11674463, 11674463)
One reference that might assist can be found at:
https://gist.github.com/josephmisiti/940cee03c97f031188ba7eac74d03a4f
Please read the notes he has included.
This is the input I have been using.
6
a b c aa d b
1 2 3 4 5 6
3
1 5 caaab
0 4 xyz
2 4 bcdybc

get next highest value in BST

I wrote a function to get the next highest value in a binary search tree and return 0 if the input value is the highest in the tree:
def getNext(root, x):
if x > root.d:
if root.r == None:
return 0
else:
if x > root.r.d:
getNext(root.r, x)
else:
temp = root.r
while temp.l != None:
temp = temp.l
return temp.d
else:
if root.l == None:
return root.d
elif x < root.l.d:
getNext(root.l, x)
else:
temp = Node('')
temp = root.l.r #53
if temp.d > x:
getNext(temp, x)
else:
while temp != None:
if temp.r == None:
return root.d
elif x > temp.r.d:
temp = temp.r
else:
getNext(temp.r, x)
break
but it only returns None
I have tried adding a print before the return, and the print actually outputs correctly
Add a return before every recursive call, i.e.
return getNext(root.r,x)
return getNext(root.l,x)
return getNext(temp,x)
return getNext(temp.r,x)

Evaluating infix expression with two stacks in python

This is my first time asking a question on here, and I am only doing this because I have spent the past week trying to figure this out and haven't been able to. I found similar questions, but the results did not help me. I have to take an infix expression and calculate the results using two stacks, one for the operator and one for the numbers. An example would be 6 - ( 5 - 3 ) * ( 4 + 2 ) = -6 or 3 * 11 / 8 + 5 – 4 * 7 = -18.875. I just cannot figure out how to get this to work. Currently my code is this:
class NumStack:
def __init__(self):
"""Create an empty stack."""
self._data = [] #nonpublic list instance
def __len__(self):
"""Return the number of elements in the stack."""
return len(self._data)
def is_empty(self):
"""Return True if the stack is empty."""
return len(self._data) == 0
def push(self,e):
"""Add element e to the top of the stack."""
self._data.append(e) #new item stored at end of list
print(self._data)
def top(self):
"""Return (but do not remove) the element at the top of the stack.
Raise Empty exception if the stack is empty"""
if self.is_empty():
return
return self._data[-1] #the last item in the list
def pop(self):
"""Remove and return the element from the top of the stack (i.e, LIFO)
Raise Empty exception if the stack is empty."""
if self.is_empty():
return "empty"
return self._data.pop() #remove last item from list
def str(self):
return self._data
class OperatorStack:
def __init__(self):
"""Create an empty stack."""
self._data = [] #nonpublic list instance
def __len__(self):
"""Return the number of elements in the stack."""
return len(self._data)
def is_empty(self):
"""Return True if the stack is empty."""
length = len(self._data)
if length == 0:
return True
else:
return False
def push(self,e):
"""Add element e to the top of the stack."""
self._data.append(e) #new item stored at end of list
print(self._data)
def top(self):
"""Return (but do not remove) the element at the top of the stack.
Raise Empty exception if the stack is empty"""
if self.is_empty():
return
return self._data[-1] #the last item in the list
def pop(self):
"""Remove and return the element from the top of the stack (i.e, LIFO)
Raise Empty exception if the stack is empty."""
length = len(self)
if length == 0:
print("list is empty")
else:
if self.is_empty():
return
return self._data.pop()
def str(self):
return self._data
def main():
expression = str(input("Enter an expression: "))
expression = expression.split()
print(expression)
N = NumStack()
O = OperatorStack()
new = []
NewOP = []
NewNum = [0,0]
for e in expression:
if e == '(' or e == ')' or e == '+' or e == '-' or e == '*' or e == '/':
O.push(e)
else:
N.push(e)
while O.is_empty() == False or N.is_empty() == False:
TmpOp = O.top()
if TmpOp == ')':
O.pop()
elif TmpOp == '(':
O.pop()
if TmpOp != '(' and TmpOp != ')':
new.append(N.pop())
new.append(O.pop())
print(TmpOp)
while TmpOp == ')':
if N.top() != "empty":
NewNum[1] = N.pop()
if N.top() != "empty":
NewNum[0] = N.top()
print(NewNum[0],NewNum[1])
if O.pop() == '+':
num = float(NewNum[1]) + float(NewNum[0])
new.append(num)
print(num)
O.pop()
break
elif O.pop() == '-':
num = float(NewNum[0]) - float(NewNum[1])
new.append(num)
print(num)
O.pop()
break
elif O.pop() == '*':
num = NewNum[1]*NewNum[0]
new.append(num)
print(num)
# O.pop()
break
elif O.pop() == '/':
num = NewNum[1]/NewNum[0]
new.append(num)
print(num)
# O.pop()
break
if O.top() == ')':
O.pop()
break
if O.__len__() == 0 and N.__len__() == 0:
break
continue
while TmpOp != ')' and TmpOp != '(':
new.append(N.pop())
new.append(O.pop())
print(new)
if O.__len__() == 0 and N.__len__() == 0:
break
print(new)
main()
I believe my classes to be correct, I just cannot find a way of extracting the needed information correctly. I am trying to pop the items into a list and when I get to a parenthesis I go ahead and perform the calculation. If I could just get the correct numbers into my list then I know I can get it to work. I just need to get the "new" to contain the correct numbers. With the problem: "6 - ( 5 - 3 ) * ( 4 + 2 )" I should get [6.0, '*', 2.0, '-', 6]. It is not coming out to that. I really appreciate any help that can be given.

Counting number of nodes in a Binary Search Tree

I am trying to print the size of my binary search tree. However, what my code is doing now is printing what level each node is at. I feel as though I am putting my count += 1 in the wrong place or perhaps it might be something else. I was wondering if someone could be an extra set of eyes for me and give me a hint on how I can fix this.
output:
3
3
2
3
3
2
1
expected output:
7
my code:
def BST_size(root, count = 0):
if root is None:
print "size -1 (Null value in root)"
if root is not None:
count += 1
if root.left is not None:
BST_size(root.left, count)
if root.right is not None:
BST_size(root.right, count)
print count
Extra parts:
class Node:
def __init__(self,value):
self.right = None
self.left = None
self.value = value
def BST_Insert(root, node): # root --> root of tree or subtree!
if root.value is None:
root = node # beginning of tree
else:
if root.value > node.value: # go to left
if root.left is None:
root.left = node
else:
BST_Insert(root.left, node)
if root.value < node.value: # go to right
if root.right is None:
root.right = node
else:
BST_Insert(root.right, node)
r = Node(4)
# left
a = Node(2)
b = Node(1)
c = Node(3)
# right
d = Node(8)
e = Node(6)
f = Node(10)
BST_Insert(r, a)
BST_Insert(r, b)
BST_Insert(r, c)
BST_Insert(r, d)
BST_Insert(r, e)
BST_Insert(r, f)
There are two ways to do this.
The easy way is to return the count from each recursive call, instead of just printing it, and increment:
def BST_size(root):
if root is None:
return -1
if root is not None:
if root.left is not None:
return 1 + BST_size(root.left)
if root.right is not None:
return 1 + BST_size(root.right)
def print_BST_size(root):
size = BST_size(root)
if size == -1:
print "size -1 (Null value in root)"
else:
print "size", size
However, that still doesn't work, because you're only traversing the left side or the right side, not both. What you want is:
count = -1
if root is not None:
if root.left is not None:
count += BST_size(root.left)
if root.right is not None:
count += BST_size(root.right)
return count
However, it looks like you're trying to use an accumulator, in tail-recursive style. There's really no point in doing this in Python, because Python doesn't optimize tail calls, but it's a useful skill to learn for other languages and for theoretical reasons, so…
The problem here is that you need the same value to be shared by all of the recursive calls, which means you need a mutable value. So, you can start with [0] instead of 0, and do count[0] += 1 instead of count += 1.
Or you can rearrange your code so that it doesn't use count mutably, and instead passes the updated count from one side down to the other.
Either way, you've got another problem with your code. Your recursive base case is that root is None. But you've also made it a special case, printing -1 instead of 0. You can't have it both ways.
def BST_size(root, count = 0):
if root is None:
return count
return BST_size(root.left, BST_size(root.right, count + 1))
def BST_size(root):
if root is None:
return 0
else:
return BST_size(root.left) + BST_size(root.right) + 1
print "Size is: " + str(BST_size(r))
if root is not None:
count = 1
if root.left is not None:
count += BST_size(root.left, count)
if root.right is not None:
count += BST_size(root.right, count)
return count
Here is a short answer
You have to do tree treversal, where the function returns the number of nodes below + 1 (itself)
Pseudo code:
def counter(t):
rCount = counter(t.right)
lCount = counter(t.left)
return 1 + rCount + lCount
You could use something like this:
def countNodes(root):
count = 1
if root is None:
return -1
if root is not None:
if root.left is not None:
count += countNodes(root.left)
if root.right is not None:
count += countNodes(root.right)
return count
and invoke it like below:
print ("\nCount of Nodes :" + str(countNodes(root)))

Categories