Python: traverse tree adding html list (ul) - python

I have this python code that will traverse a tree structure. I am trying to add ul and li tags to the function but I am not very succesful. I though I was able to keep the code clean without to many conditionals but now I ain't so sure anymore.
def findNodes(nodes):
def traverse(ns):
for child in ns:
traverse.level += 1
traverse(child.Children)
traverse.level -= 1
traverse.level = 1
traverse(nodes)
This is the base function I have for traversing my tree structure. The end result should be nested ul and li tags. If need I can post my own not working examples but they might be a little confusing.
Update: Example with parameter
def findNodes(nodes):
def traverse(ns, level):
for child in ns:
level += 1
traverse(child.Children, level)
level -= 1
traverse(nodes, 1)

I removed the unused level parameter. Adding in any sort of text is left as an exercise to the reader.
def findNodes(nodes):
def traverse(ns):
if not ns:
return ''
ret = ['<ul>']
for child in ns:
ret.extend(['<li>', traverse(child.Children), '</li>'])
ret.append('</ul>')
return ''.join(ret)
return traverse(nodes)

Related

Populate binary decision tree from indented file in C#

I have nested if-else statements generated by the D4.5 algorithm from a dataset in python. I want to transform this into a binary decision tree in Unity C# so I can traverse through it with my NPCs to create simple data-driven AI.
This is my input (currently indented by tabs but I can change it to a sequence of chars or just a number which tells me what level I am currently at):
HP is > 0:
SeesEnemy is False:
HearEnemy is False:
Idle
HearEnemy is True:
Seeking
SeesEnemy is True:
EnemyInRange is True:
Attacking
EnemyInRange is False:
Chasing
HP is <= 0:
Dead
And I want Tree like this with negative child on left and positive on right:
Tree
I do not have a problem with the implementation or traversing a tree but with the creation of it from data.
Another variant would be to transform input to this format, which I can deserialize to desired tree:
"HP > 0?,Dead,#,#,SeesEnemy?,HearEnemy?,Idle,#,#,Seeking,#,#,EnemyInRange?,Chasing,#,#,Attacking,#,#"
Where # means there is no child on left side and #,# means there are no children at all. This could be ideally done on python side.
I tried to read the input line by line while the number of tabs at the start of the line was incrementing like in the Depth-first search. My idea was to create a child of a current node on the left or right side based on false/true (<=/>) and return to the parent when the indentation of the next line was smaller than the previous one and continue with another side. But there was a problem with pointing to the current node.
I also tried to parse the file in levels (level 0 was "HP is > 0" and "HP is <= 0" etc.) but there were other problems which I could not solve.
I think there is some elegant recursion way to do this but I cannot find it nor figure it out itself. Thanks.
Instead of building Data Structure Tree and then make a decision traversing, you can build it through expressions. Straight with your boolean conditions and actions and lazy execution of branches. Just traverse your file and build it through expression tree iterator:
https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/expression-trees/
Then, when you got your final expression you can just invoke (compile and invoke) and it will give you result. I built several DSL on this for my work, which are more complex (with bodies, loops, etc) than your case, so you should be fine.
If you struggle with parsing/traversing you can read more about bottom-up parsing on wiki - https://en.wikipedia.org/wiki/Bottom-up_parsing
To say it simple, you just create stack of simple expressions out of you file (usually constants or simple boolean conditions) and as you go through file, when something complete formed at the tail you transform tail (one or more elements) to next expression, then continue until you parsed entire file.
Here is a way to create a tree, using a stack while reading the input string
import re
class Node:
def __init__(self, data, condition=None):
self.data = data
self.condition = condition
self.left = self.right = None
def add(self, data, test):
node = Node(data, test)
if not self.right and self.condition != "False":
self.right = node
else:
self.left = node
if self.condition in ("False", "True"):
self.condition = ""
return node
def preorder(self):
if self:
yield self.data + (" " + self.condition if self.condition else "") + ("?" if self.condition is not None else "")
yield from Node.preorder(self.left)
yield from Node.preorder(self.right)
else:
yield "#"
def tree(s):
stack = [(-1, Node(None))]
nodedepth = -1
for match in re.finditer(r"([ ]*)(\S+)(?: is (.*?):)?[ ]*$", s, re.M):
depth = len(match[1])
while depth <= stack[-1][0]:
nodedepth, node = stack.pop()
parent = stack[-1][1]
stack.append((depth, node if nodedepth == depth else parent.add(match[2], match[3])))
return stack[0][1].right
The tree function makes the tree from a string. The preorder method can be used to generate the serialized output string in the format you gave (with the hashes).
Example run:
s = """HP is > 0:
SeesEnemy is False:
HearEnemy is False:
Idle
HearEnemy is True:
Seeking
SeesEnemy is True:
EnemyInRange is True:
Attacking
EnemyInRange is False:
Chasing
HP is <= 0:
Dead"""
root = tree(s)
print(",".join(root.preorder()))
Output:
HP > 0?,Dead,#,#,SeesEnemy?,HearEnemy?,Idle,#,#,Seeking,#,#,EnemyInRange?,Chasing,#,#,Attacking,#,#

Create a Tree of Object Recursively (Python)

i would like to create a tree of objects called State.
Each State has a list of 4 robots and each states have differents robots coordinates.
The goal is to create a graph which will be solved by a Breadth First Search Algorithm.
(The original game is RicochetRobot maybe you guys know it).
class State:
def __init__(self,parent,childs,robots,cpt,):
self.parent = parent
self.childs = childs
self.robots = robots
self.cpt = cpt
I created a function create_child to do this
def create_child(self,depth):
#UP
#Depth is the tree height
if depth==0:
print("STOP")
return
else :
for i in range(4):
#Copying the robots of the current object
temp = copy.deepcopy(self.robots)
#Getting robot to move index
temp_robot = temp[i]
#removing this robot from the list
temp.pop(i)
#Moving up the robot and inserting it in the list
#Moving up is a simple function which increment the y of the robot
temp.insert(i,moving_up(temp_robot,create_board(init_robot())))
#Adding a new child into childs list
self.childs.append(State(self,self.childs,temp,self.cpt+1))
#Decrementing the depth
depth-=1
#Recursivity
for child in self.childs:
child.create_child(depth)
My problem is that when depth = 0 , it print STOP,but it doesnt return None, and the function keep going.
Anynone knows from where it come froms?
Also, if you can give advice on how to make my tree in an easier way it would be nice.
Alright so i think i found a solution , here it is :
depth = 1
parent = Initial_State
for j in range(depth):
for i in range(len(parent.childs)-1):
parent.childs[i].create_child()
parent = parent.childs[i]
It seems to be working. I dont use recursion anymore, i do it in a more iterative way and outside the function and it seems good.
Thank you

return top 5 most visited websites (heap, hashtable) - Python

Design and implement a web browser that supports the functionality that at any given instance
you can efficiently tell the top 5 visited websites on basis of the number of visits (in any order)
In my implementation, I did not use the Webpage class as I can't think of an efficient way we could update the heap based on visits unless we did heapify again. I don't think I can update the heap "on the go". If I use the Webpage class to track visits instead of the hashtable I would still need to update the hashtable every time I visit a site.
I want to understand how I can optimize this solution in PYTHON. I have seen implementations in C++, but I want to know if I can optimize my current implementation in my language of choice. Any insight would be great.
class Webpage:
def __init__(url):
     self.url = url
self.numberOfVisits = 1
  
class History:
def _init_():
self.sites = {}
    def visit(url):
if (url in self.sites):
self.sites[url] += 1
else:
self.sites[url] = 1
    def printTop5():
heap = []
heapq.heapify(heap)
for key, value in self.sites:
heap.heappush(heap, (-value, key))
i = 0
while (heap and i < 5):
value, url = heapq.heappop(heap)
print(url)
i += 1
def main():
    History h = History();
    print("before visits\n")
    h.visit("www.google.com")
    h.visit("nytimes.com")
    h.visit("reddit.com")
    h.visit("dev.ibm.com")
    h.visit("www.google.com")
    print("after visits\n")
    h.printTop5()
    h.visit("ig.com")
    h.visit("ig.com")
    h.visit("ig.com")
h.printTop5()
Technically, the best way to implement this in Python is to use the built in collections.Counter datatype. This is written in highly optimized code and will probably yield the best performance possible with Python. You can read more about it in the documentation [here] (https://docs.python.org/3/library/collections.html#collections.Counter).
So for example:
from collections import Counter
history = Counter()
#I made them one by one to signify individal browser requests
history["google.com"] += 1
history["yahoo.com"] += 1
history["spotify.com"] += 1
history["yahoo.com"] += 1
history["bing.com"] += 1
history["youtube.com"] += 1
history["amazon.com"] += 1
history["yahoo.com"] += 1
history["google.com"] += 1
history["wikipedia.com"] += 1
history["wikipedia.com"] += 1
history["yahoo.com"] += 1
history["yahoo.com"] += 1
history["amazon.com"] += 1
print(history.most_common(5))
And this returns:
[('yahoo.com', 5), ('google.com', 2), ('amazon.com', 2), ('wikipedia.com', 2), ('spotify.com', 1)]
Since this comes with a standard installation of Python, I think this should count as "pure" python.
Possible global heap
I am wondering if there is an efficient way to use a global heap
I don't think a global heap could work efficiently. To update a heap when an entry changes (so-called increase-key or decrease-key operations), it suffices to run siftup or siftdown starting at the changed node. However, you first have to find the position of then node within the heap, and we don't have an efficient way to do that.
Alternative data structure
... or something?
There is another way. Create a doubly linked list with links in the form, Link(prev, next, count, url). Track two variables, first and last, to track the endpoints of the doubly linked list. Use a dictionary (hash table) to map from the url to the link entry.
The visit(url) code is responsible for updating the structure.
If the url hasn't been seen before, create a new link, Link(prev=last, next=None, count=1, url), save the link in your site dictionary with site[url] = new_link, append the link the doubly linked list, and update last with last = new_link.
If the url has been seen before, find with link with link = site[url] and update the count with link.count += 1. To maintain the most-common-to-least common sort order, keeping swapping with previous links while link.count > link.prev.count.
This can be optimized further by keeping links with the same count in a pool so that at most one swap will occur.
Whenever printTop5() is called, just traverse the first five entries in the doubly-linked list starting with first.
Working code
from dataclasses import make_dataclass
Link = make_dataclass('Link', ('prev', 'next', 'url', 'count'))
class History:
def __init__(self):
self.site = {}
self.root = root = Link(None, None, 'root', 0)
root.prev = root.next = root
def visit(self, url):
root = self.root
if url in self.site:
link = self.site[url]
link.count += 1
while link.prev is not root and link.prev.count < link.count:
prev = link.prev
prev.prev.next = link
link.next.prev = prev
prev.next, link.next = link.next, prev
prev.prev, link.prev = link, prev.prev
else:
last = root.prev
link = Link(last, root, url, 1)
self.site[url] = root.prev = last.next = link
def printTop5(self):
link = root = self.root
for i in range(5):
if link.next is not root:
link = link.next
print(link.count, link.url)

local variable might be referenced before assignment in Python

I'm going through some code that implements a decision tree learner.
Here is the code:
def calculate_entropy(self, tags):
tags_counter = Counter()
if len(tags) > 0:
for tag in tags:
tags_counter[tag] += 1
classes_probs = [float(tags_counter[tag]) / len(tags) for tag in tags_counter]
entropy = 0
for prob in classes_probs:
if prob == 0:
return 0
entropy -= prob * math.log(prob, 2)
return entropy
else:
return 0
My questions are:
for classes_probs I get a local variable might be referenced before assignment message, and I can't figure why.
what does the code on the right side of the placement into classes probs do? I haven't seen anything like it.
(1) The warning is because classes_probs may be undefined at that point. If tags is empty, the first loop doesn't execute. You can "fix" this by assigning an empty list before the first loop.
(2) This is called a list comprehension. Use that search term and find a tutorial at your preferred level of writing and examples.

Recursion and Binary Trees

#Get length of the longest path through recursion
def max_height(node):
if not node:
return 0
left = max_height(node.left) #Base Case based on my understanding
right = max_height(node.right) #Base Case based on my understanding
return max_height(left, right) + 1
I keep calling the max_height to get the length but I'm getting an error. I've thought of three possibilities:
1) I misunderstand the concept of the base case and I don't actually have a base case.
2) I'm not properly spacing Python code.
3) I'm not recursively getting the height of the BST at all but rather the width of the tree, which is affecting later calculations.
I know it is similar to this question, but the main difference is that I'm really trying to use recursion , where the other question used iteration and merely called it recursion.
how to find the height of a node in binary tree recursively
The base case is where the recursion stops and you have one: not node (node == None)
I don't see an issue with the spacing... Make sure you use only tabs or only spaces
This does produce the height: the number of nodes from root to leaf along the longest root-leaf path. At every node level, you add 1, and follow the higher subtree.
def max_height(node):
if not node: # this is the base case:
return 0 # where all recursive calls eventually stop
left = max_height(node.left) # <- these are the recursive calls:
right = max_height(node.right) # <- function x is called inside function x
return max(left, right) + 1 # max here, not max_height
Note that this is merely a more verbose version of this answer to the question you linked.
All answered were right but, I faced little problem while writing inside the class;
So, the code goes like this, I hope this helps.
class Tree(object):
def height(self, root):
if root == None: #root == None
return 0
else:
return 1 + max(self.height(root->left), self.height(root->left))
t = Tree()
t.height(t)

Categories