I am trying to write a function to count the repetitive node in a Binary Search Tree (assume that this tree accept repetition). Here is a line of code that I have
def count(treeroot,item,y):
if treeroot==None:
return 0
elif treeroot.getData()==item:
return 1
else:
return count(treeroot.getLeft(),item,y)+count(treeroot.getRight(),item,y)
where y is the starting number of the search (such as search for how many 10 in the tree, we do count(treeroot,10,0)
However, I tried to put 3 number 10 in and I only receive back the count of 1.
Can anyone tell me what is wrong with my code and how to fix it
You stop recursing down the tree as soon as you found the first item. You need to keep recursing:
def count(treeroot,item,y):
if treeroot==None:
return 0
elif treeroot.getData()==item:
return 1 + count(treeroot.getLeft(),item,y)+count(treeroot.getRight(),item,y)
else:
return count(treeroot.getLeft(),item,y)+count(treeroot.getRight(),item,y)
I hope you see the problem with your algorithm though: You will visit each and every node of the tree, even if you know that there will be no 10s to the left of 9s or to the right of 11s.
Related
I have been learning binary trees lately and have looked through the code for counting the leaves.
This is the recursive function to count the leaves:
def __count_leaves_recursive(self, node):
if node == None:
return 0
elif node.left == None and node.right == None:
return 1
else:
return self.__count_leaves_recursive(node.left) + self.__count_leaves_recursive(node.right)
When learning how recursion works with trees, the Python Tutor visualisation tool has been invaluable. However it hasn't helped me visualise the final return statement. I am struggling to visualise what's happening when a recursion function is added to another recursive function in the same line.
Is it simply the same as any other time the program reaches a recursive function? In that, the program simply records where it enter the function in order to return to the same spot when the function has been completed?
Is it simply the same as any other time the program reaches a recursive function?
Yes, you can image that line of code like this:
a = self.__count_leaves_recursive(node.left)
b = self.__count_leaves_recursive(node.right)
return a + b
So the first recursive call has to finish completely before the second one is launched. When that second recursive call also has finished its job, both returned values are summed up, and that value is returned to the caller.
wondering if anyone can give me some advice for using Selenium with Python for webscraping.
I need to get the number of elements with a certain class on a page, and I have it working well with
driver=webdriver.PhantomJS()
driver.get('https://www.somerandomsite.com/1')
number_of_elements = len(driver.find_elements_by_class_name('some_class'))
this gets the right number of elements every time.
But now I want to define a function so it can scrape multiple webpages - say https://www.somerandomsite.com/1 to https://www.somerandomsite.com/10
So I do
driver=webdriver.PhantomJS()
def my_func(start,end)
while start <= end:
driver.get('https://www.somerandomsite.com/'+str(start))
number_of_elements = len(driver.find_elements_by_class_name('some_class'))
start += 1
Theoretically, this should move onto the next page, and retrieve the number of classes that I want in that page. However, it works fine for the first page, but subsequent pages yield a number of elements that's either equal to the number of elements of the previous page plus that of the current page, or that sum minus 1. If I use an xpath instead of a class name selector I get the exact same results.
Also, if I try to access any elements that are in that longer list, it throws an error since only the values on that page actually exist. So I have no idea how it's getting that longer list if the elements on it don't even exist. (For example, if there are 8 elements on page one and 5 elements on page two, when it gets to page two it'll say there are 12 or 13 elements. If I access elements 1-5 they all return values, but trying to call the sixth element or higher will cause a NoSuchElementException.)
Anyone know why this might be happening?
EDIT: I've narrowed it down a bit more, hopefully this helps. Sorry I was off in the initial question.
driver=webdriver.PhantomJS()
def my_func(start,end)
while start <= end:
driver.get('https://www.somerandomsite.com/'+str(start))
number_of_elements = len(driver.find_elements_by_class_name('some_class'))
start += 1
So the above code actually works. However, when I then navigate to another page that also has elements of 'some_class', and then continue looping, it adds the number of elements from the previous page to the current page.
So my code's like this:
driver=webdriver.PhantomJS()
def my_func(start,end)
while start <= end:
driver.get('https://www.somerandomsite.com/'+str(start))
number_of_elements = len(driver.find_elements_by_class_name('some_class'))
print(number_of_elements)
driver.get('https://www.somerandomsite.com/otherpage')
start += 1
my_func(1,2)
So let's say https://www.somerandomsite.com/1 has 8 elements of class 'some_class', https://www.somerandomsite.com/otherpage has 7 elements of class 'some_class', and https://www.somerandomsite.com/2 has 10 elements of class 'some_class'.
When I run the above code, it'll print 8, then 17. If I don't navigate to the other page, and run
driver=webdriver.PhantomJS()
def my_func(start,end)
while start <= end:
driver.get('https://www.somerandomsite.com/'+str(start))
number_of_elements = len(driver.find_elements_by_class_name('some_class'))
start += 1
So the above code actually works. However, when I then navigate to another page that also has elements of 'some_class', and then continue looping, it adds the number of elements from the previous page to the current page.
So my code's like this:
driver=webdriver.PhantomJS()
def my_func(start,end)
while start <= end:
driver.get('https://www.somerandomsite.com/'+str(start))
number_of_elements = len(driver.find_elements_by_class_name('some_class'))
print(number_of_elements)
start += 1
my_func(1,2)
it'll print 8 then 10, as I want it to. I'm not sure why it's counting elements on two pages at once, and only if I get that other page beforehand.
EDIT2: So I've gotten it working by navigating to a page on a different server and then returning to the page I want. Weird, but I'll use it. If anyone has any ideas on why it doesn't work if I don't though I'd still love to understand the problem better.
Difficult to tell what - if at all - the problem is as you don't provide the necessary details to replicate what you're describing.
IMHO a function is overkill for this simple task. Just toss it and create the loop. In general I'd put the loop outside.
Also you need a function call for this to do anything at all - and a return statement.
In general for similar stuff I'd put the loop outside the function.
Like so:
def my_func(driver, count):
driver.get('https://www.somerandomsite.com/%d' % count)
number_of_elements = len(driver.find_elements_by_class_name('some_class'))
return number_of_elements
driver=webdriver.PhantomJS()
total_element_count = 0
count = 1
while count < 1000: # or whatever number you need
number_of_elements = my_func(driver, count)
total_element_count += number_of_elements
print("[*] Elements for iteration %d: %d" % (count, number_of_elements))
print("[*] Total count so far: %d" % total_element_count)
count +=1
Take a look at
number_of_elements = len(driver.find_elements_by_class_name('some_class'))
You asign len of elements on each iteration, but instead you need to sum them, so your code should look like:
driver=webdriver.PhantomJS()
def my_func(start,end):
count = 0
while start <= end:
driver.get('https://www.somerandomsite.com/'+str(start))
count += len(driver.find_elements_by_class_name('some_class'))
start += 1
I have a question about coding up a binary tree, and I'm currently stuck on it.
Basically, the algorithm is as follows where at the initial node, we have the following objects: 1,2,3 placed in order as (None,2,3) with object 3 > object 2 > object 1. In each stage of the tree, one object can move to their immediate right or left and be placed with another object if that object that is moving is smaller than the object that is placed at the current position. If the position to the immediate right or left has a None position, then only the smallest number may move over from the right or left position. For example, it is possible to have the events of (None,0,2+3) and (None,1+2,3) after the initial node.
Hence, the tree is as follows:
I am wondering how to code this up in Python. I dont really care about the replicating events so at each point, I am only interested in the unique tuples/events that occurs.
Im not sure but a rough idea I have is to do this:
def recursion():
pos = list(range(1,4))
index = 0
values = list(range(1,4))
tree = []
if pos[index+1] > pos[index]:
pos[index + 1] -= pos[index+1]
pos[index + 2] += pos[index+1]
tree.append(pos)
if pos[index+1] < pos[index]:
pos[index+1] += pos[index]
pos[index] -= pos[index]
tree.append(pos)
else:
recursion()
return tree
Any help would be greatly appreciated.
I am having a problem trying to fill the data a perfect binary tree with a known number of nodes with the correct data. Basically, I have an implementation that creates this:
7
5 6
1 2 3 4
However, I am looking to create a tree like this:
7
3 6
1 2 4 5
My current implementation for inserting the nodes of a tree is as follows.
def _add_node(self, val, ref = None):
# reference to root of tree
ref = self.root if ref is None else ref
if ref.right is None:
ref.right = Node(val, ref)
return
elif ref.left is None:
ref.left = Node(val, ref)
return
else:
parent = (val - 1) / 2
if parent % 2 == 0:
self._add_node(val, ref.left)
else:
self._add_node(val, ref.right)
Given x nodes I create a tree using range(x) and calling add_node(i) for each iteration. This works fine except its order is incorrect.
For the life of me I cannot figure out an easy way to set the values to represent the bottom layout rather than the top. Can anyone help me out?
This seems to be an issue with the order that you are entering data in. How are you passing in the data?
Also think about your implementation. You check to see whether the right child is empty and if it is you place the node there. However, if it isn't you move on to the left node. This is where the issue is happening.
Assuming you are passing in the data in reverse chronological order you start with 7 at the root. Then you move to 6 which you place in the right node. Then move on to 5; you check to see whether the right node is empty, which is isn't because it is filled with 6, so you move on to check if the left node is empty and find that it is. So you place 5 there.
Do you see the issue?
You need to figure out a way to get around this issue, but hopefully this was good in helping you debug.
Good Luck!
I am quering a database for some paramaters which depend on a attribute called count! count can be incremented incase the 1st query does not return anything. Here is a sample code
sls = {(213.243, 55.556): {}, (217.193, 55.793): {}, (213.403, 55.369): {}}
for key in sls.keys:
if not sls[key]:
ra, dec = key[0], key[1]
search_from_sourcelist(sl, ra,dec)
count = 1
def search_from_sourcelist(sl, ra,dec):
dist = count/3600.0
sls[(ra,dec)] = sl.sources.area_search(Area=(ra,dec,dist))
return
Incase i run the method search_from_sourcelist, and it doesnt return anything, i would like to increment count, and do the query again. This is to be done for all keys in sls dictionary, untill all the keys have a value!!
Here is the most fundamental recursive function
def countdown(n):
if n == 0:
return "Blastoff"
else:
print "T minus %s" % n
return countdown(n-1)
You will notice that countdown returns itself with a modified argument, in this case n but -1, so if you actually followed this all the way through you would get
(-> indicates a call)
countdown(5) -> countdown(4) -> countdown(3) -> countdown(2) -> countdown(1) -> countdown(0) #stop
So now you understand what a recursive function looks like you realize you never actually return a call of your own function, thus your code is not recursive
We use recursion because we want to boil a task down to its simplest form then work from there, so a good example of this would be the mcnuggets problem. So you need to tell us what you are trying to achieve and how it can be made a smaller problem (or more importantly why.) Are you sure you cannot do this iteratively? remember you don't want to blow your stack depth because python is NOT tail recursive by standard
Recursion is useful when you find a way to reduce the initial problem to a "smaller version of itself".
The standard example is the factorial function
def fac(n):
return n * fac(n-1) if n > 1 else 1
Here you reduce the problem of calculating the factorial of n to calculating the factorial of n-1.
In your code there is no such "reduction". You just increment a value and start the same problem over again. Thus, I recommend you solve it iteratively.
I'm not sure that you need a recursive algorithm for this.
Incase i run the method search_from_sourcelist, and it doesnt return anything, i would like to increment count, and do the query again. This can be done with a while loop as follows:
for key, value in sls.iteritems():
if not value:
ra, dec = key[0], key[1]
count = 1
while not search_from_sourcelist(sls, ra, dec):
count += 1
But if you really do want to do this recursively, you can do it as follows, leave a comment and I'll write it up.
Further, you should look into your search_from_sourcelist function, as it always returns None