Skip to content
Snippets Groups Projects
Commit f0265f9b authored by Romain Vuillemot's avatar Romain Vuillemot
Browse files

lab 10

parent 93f5532a
No related branches found
No related tags found
No related merge requests found
%% Cell type:markdown id:4ef6c0ef-cf70-45dd-af93-5a910c414ea1 tags:
# UE5 Fundamentals of Algorithms
# Lab 9: Trees
%% Cell type:markdown id:34c7a5e4-9f95-48fc-9729-5b0b7c76ea64 tags:
---
%% Cell type:markdown id:c62d36f3-db61-40b0-add2-d2da652708fd tags:
## Exercise 1: Compare two trees data structures
You are given a tree data structure as a dictionnary, e.g:
%% Cell type:code id:58d3c26d-d101-45d3-9283-44427258854b tags:
``` python
tree_dict = {
'a': ['b', 'c'],
'b': ['d', 'e'],
'c': ['f'],
'd': [],
'e': [],
'f': []
}
```
%% Cell type:markdown id:134fc918-8d81-43f8-b847-be70b3047d25 tags:
And another one as an Object:
%% Cell type:code id:deea1d47-404d-43df-adee-5c49427598c8 tags:
``` python
class Node:
def __init__(self, value = None, children = []):
self.value = value
self.children = children
```
%% Cell type:markdown id:c77a0f57-7f47-4eb7-b673-1972398106c7 tags:
Implement the following:
1. Use the above data structure to store the first 6 letters of the alphabet in alphabetical order (if the tree is traversed using bfs)
2. A bfs function to compare the trees (i.e. the bfs function returns the same nodes in the same order)
%% Cell type:code id:59f3995a-3e79-401b-8813-7543037841b2 tags:
``` python
### BEGIN SOLUTION
node_d = Node('d')
node_e = Node('e')
node_f = Node('f')
node_b = Node('b', [node_d, node_e])
node_c = Node('c', [node_f])
root = Node('a', [node_b, node_c])
def bfs_tree_dict(tree_dict, root):
queue = [root]
traversal_order = []
while queue:
node = queue.pop(0)
traversal_order.append(node)
for child in tree_dict.get(node, []):
queue.append(child)
return traversal_order
def bfs_tree_node(root):
if root is None:
return []
queue = [root]
traversal_order = []
while queue:
node = queue.pop(0)
traversal_order.append(node.value)
for child in node.children:
queue.append(child)
return traversal_order
assert bfs_tree_dict(tree_dict, 'a') == list(tree_dict.keys())
assert bfs_tree_node(root) == bfs_tree_dict(tree_dict, 'a')
### END SOLUTION
```
%% Cell type:markdown id:0ee4bcec-c701-4558-b35d-4ce49a953f47 tags:
## Exercise 2: Return the list of links from a tree
Given the two data structure from the previous exercise (i.e. dict and object), return the list of links of those two trees in the same order and compare them. Return `-1` if the trees have a cycle.
%% Cell type:code id:f521a89e-c319-4180-94e1-adb1cd7832ad tags:
``` python
def get_edges_node(root):
if root is None:
return []
edges = []
visited = set()
stack = [root]
while stack:
node = stack.pop(0)
if node in visited:
return -1
visited.add(node)
for child in node.children:
edges.append([node.value, child.value])
stack.append(child)
return edges
```
%% Cell type:code id:78392fbd-7887-4e91-b006-8785e1d135d4 tags:
``` python
def get_edges_dict(tree_dict, start_node):
### BEGIN SOLUTION
edges = []
queue = [start_node]
visited = set()
while queue:
parent = queue.pop(0)
if parent in visited:
continue
visited.add(parent)
for child in tree_dict.get(parent, []):
edges.append([parent, child])
if child not in visited:
queue.append(child)
return edges
### END SOLUTION
```
%% Cell type:code id:f711a8a8-420c-4eff-9227-90c9b933bdba tags:
``` python
assert get_edges_dict(tree_dict, 'a') == get_edges_node(root)
```
%% Cell type:markdown id:8b7b3ed0-771b-49b4-b1ca-4d7ffde0cae5 tags:
## Exercise 3: Calculate the total weight of a weighted tree
Update the two previous data structure to store a weight value. The weight is stored in links and is any numerical value. For the dictionnary, adapt the data structured using named values as below. Provide examples of weighted trees similar as the previous questions (you assign random weights, if no weight then assign `0`).
%% Cell type:code id:0780439e-6d76-4576-9669-0c94c8a7b476 tags:
``` python
tree_dict_weight = {
"a": {"neighbors": ["b", "c"]},
"b": {"neighbors": ["d", "e"]},
"c": {"neighbors": ["f"]},
"d": {"neighbors": []},
"e": {"neighbors": []},
"f": {"neighbors": []}
}
```
%% Cell type:code id:8209cb32-7d73-44a4-af00-85d73a80f5ca tags:
``` python
### BEGIN SOLUTION
class Node_weight:
def __init__(self, data, weight=0):
self.data = data
self.children = []
self.weight = weight
tree = Node_weight(1)
child1 = Node_weight(2, weight=5)
child2 = Node_weight(3, weight=7)
tree.children = [child1, child2]
def get_tree_edges(root):
edges = []
stack = [(root, None)]
while stack:
node, parent_data = stack.pop()
for child in node.children:
stack.append((child, node.data))
edges.append((node.data, child.data, child.weight))
return edges
sum(tpl[2] for tpl in get_tree_edges(tree))
### END SOLUTION
```
%% Output
12
%% Cell type:markdown id:6436c778-b2b4-44a1-8998-892cdab9a9e9 tags:
Write some tests
%% Cell type:code id:adf4724c-ce18-4f66-8fa2-ac5199a4fd69 tags:
``` python
### BEGIN SOLUTION
### END SOLUTION
```
%% Cell type:markdown id:7bc1c52d-1701-47d8-88ee-bc02e0188261 tags:
## Exercise 4: Check if the tree is an n-ary tree
A $n$-ary tree with $n=2$ is a binary tree. Write solution that are recursive, and for the dict and Node data structures.
%% Cell type:code id:776f8fdd-dd91-4cfc-a239-0a00bceb9e40 tags:
``` python
def is_nary_tree_dict(tree, node, n = 2, visited=None):
### BEGIN SOLUTION
if visited is None:
visited = set()
if node in visited:
return True
visited.add(node)
children = tree.get(node, [])
if len(children) > n:
return False
for child in children:
if not is_binary_tree(tree, child, n, visited):
return False
return True
is_binary_tree(tree, "A", 2)
### END SOLUTION
```
%% Cell type:markdown id:01df4470-fab0-4cc2-a58b-0c22d4ed5754 tags:
Write some tests
%% Cell type:code id:f2ef2bfb-35af-45ed-b526-6a69f8890282 tags:
``` python
def is_nary_tree_node(root, n = 2, visited=None):
### BEGIN SOLUTION
pass
### END SOLUTION
```
%% Cell type:code id:cd6d9842-f110-46e3-9869-24cfc5f301e7 tags:
``` python
### BEGIN SOLUTION
### END SOLUTION
```
%% Cell type:markdown id:9d03a5bf-205f-4a5e-9446-d57b9800e0aa tags:
## Exercise BONUS: Update the Node class with the following methods
You may progressively update the class property methods with `Node.your_method`
%% Cell type:code id:3085f09f-5bc2-4bfe-b082-46b1fc579a84 tags:
``` python
def get_children(self): # return all the children of the current node
### BEGIN SOLUTION
return [child.value for child in self.children]
Node.get_children = get_children
assert root.get_children() == ["b", "c"]
### END SOLUTION
```
%% Cell type:code id:8750c154-28e6-4165-a682-5d3995ead561 tags:
``` python
def is_root(self): # check of the current node is a root node
### BEGIN SOLUTION
pass
### END SOLUTION
```
%% Cell type:code id:bd3e2185-8c19-48ed-89e3-ae6499e2acf2 tags:
``` python
def get_nodes(self): # get all the nodes of the tree (or sub-tree)
### BEGIN SOLUTION
pass
### END SOLUTION
```
%% Cell type:code id:5a713b70-bcf9-4850-a874-750ca25c2895 tags:
``` python
def get_edges(self): # get all the edges of the tree (or sub-tree)
### BEGIN SOLUTION
pass
### END SOLUTION
```
%% Cell type:code id:aa0619f4-758e-4b67-a8f9-edfdc13b109d tags:
``` python
def get_parent(self): # return the parent of a given node
### BEGIN SOLUTION
pass
### END SOLUTION
```
%% Cell type:code id:a4f871d3-4fae-4819-8fe3-675f2f8ea310 tags:
``` python
def is_parent(self, node): # check if the parent of a given node
### BEGIN SOLUTION
pass
### END SOLUTION
```
%% Cell type:code id:55af73bd-7793-402c-b1aa-cf976420c904 tags:
``` python
def get_height(self, parent): # return the height of a node
### BEGIN SOLUTION
pass
### END SOLUTION
```
%% Cell type:code id:be881a18-5e7d-44ee-a59d-a3211bc4d9c4 tags:
``` python
def get_siblings(self): # return all the nodes with the same height
### BEGIN SOLUTION
pass
### END SOLUTION
```
%% Cell type:code id:6bc87519-f219-4f42-81d9-bef7c92483ec tags:
``` python
def get_leaves(self): # get all the leaves of the sub-tree
### BEGIN SOLUTION
pass
### END SOLUTION
```
%% Cell type:code id:1ff5ce8d-4539-4c67-a249-8ce1638fbc37 tags:
``` python
def is_leaf(self): # check if a node is a leaf
### BEGIN SOLUTION
pass
### END SOLUTION
```
%% Cell type:code id:f4505be1-0f79-40f8-adfd-9bbb184d3671 tags:
``` python
def get_edges(self): # get edges of a sub-tree
### BEGIN SOLUTION
pass
### END SOLUTION
```
%% Cell type:markdown id:3fba7abb-00ea-49ff-945e-91bda370d1e6 tags:
Write tests.
%% Cell type:code id:acb7b4b0-af3b-42c0-bacb-f97d4fd2b530 tags:
``` python
### BEGIN SOLUTION
### END SOLUTION
```
%% Cell type:code id:81d762d6-42ca-444d-a633-503880364f11 tags:
``` python
```
%% Cell type:markdown id:53c1dc9b tags:
NAME:
%% Cell type:markdown id:497036b2-a410-477c-bcfa-e1dd1b02cd8a tags:
# UE5 Fundamentals of Algorithms
# Lab 10: Graphs
%% Cell type:markdown id:5876dd49-e808-4107-9b93-08ad6600bd34 tags:
---
%% Cell type:markdown id:3e08eb9a-9d3d-466a-afbe-aa1219475dc7 tags:
For the following exercices, your are given a graph data structure as a dictionnary:
%% Cell type:code id:f22d7834-bff7-4e23-b15d-4250ce39a1df tags:
``` python
g = { "a" : ["d"],
"b" : ["c"],
"c" : ["b", "c", "d", "e"],
"d" : ["a", "c"],
"e" : ["c"],
"f" : []
}
```
%% Cell type:markdown id:7c9b9b7f-0292-4761-aa41-0ebe6cfab49c tags:
## Exercise 1: Understand the graph properties
Give the graph `g` given previously, answer the following questions:
1. Draw the graph using a node-link diagram
2. Does it have a cycle?
3. Is it connected? If not, how many components?
4. Does it have a self loop?
%% Cell type:markdown id:613dbe01-f1a1-4811-96f0-fc893cc6ae24 tags:
We will now check the properties programmatically in the next questions.
%% Cell type:markdown id:2d324f2e-25d4-488b-9178-c29f52caee1a tags:
## Exercise 2: Check if the graph has a cycle
Here is a `dfs` algorithm for a graph, write a function `has_cycle` to detect if the graph `g` has a cycle.
%% Cell type:code id:b9611934-1a07-4cc5-b3be-1b18e6f50e57 tags:
``` python
def dfs(graph, start_node):
visited = set()
stack = [start_node]
while stack:
node = stack.pop()
if node not in visited:
print(node, end=' ')
visited.add(node)
for neighbor in reversed(graph[node]):
if neighbor not in visited:
stack.append(neighbor)
dfs(g, 'a') # start from node 'a'.
```
%% Cell type:code id:17ffa86d-f149-4746-9658-5c6aeb71f6d7 tags:
``` python
# YOUR CODE HERE
raise NotImplementedError()
```
%% Cell type:markdown id:849df1e9-aef3-4883-a3c0-d7f0e937315e tags:
Write tests.
%% Cell type:code id:d815ba3f-8dc5-4a2c-a908-4545e66ebbb5 tags:
``` python
assert has_cycle(g)
assert not has_cycle({'a': []})
assert has_cycle({'a': ['a']})
```
%% Cell type:markdown id:bad893ca-312e-4500-bc2e-d9420dca47a3 tags:
## Exercise 3: Check if the graph is connected
Check if all nodes can be reached.
%% Cell type:code id:714e9dff-adb1-44d9-a2de-a5eb5fc6f618 tags:
``` python
def is_connected(graph):
# YOUR CODE HERE
raise NotImplementedError()
```
%% Cell type:markdown id:d63ff45a-76d7-42d1-ae43-045cdc714b92 tags:
Write tests.
%% Cell type:code id:b59faa9a-5ed6-4795-a650-ba0bc4c6b39e tags:
``` python
assert not is_connected(g)
```
%% Cell type:markdown id:05c4b848-67a1-4aa7-9ae6-182ccca5ad82 tags:
## Exercise 4: Check if the graph has self-loop
Check if there is at least a node that links to itself.
%% Cell type:code id:ff86ab1e-574f-45d8-b9d7-cd14d7d9e81b tags:
``` python
def has_self_loop(graph):
# YOUR CODE HERE
raise NotImplementedError()
```
%% Cell type:markdown id:385d5be2-036f-448b-9b34-2a5f478eb9db tags:
Write tests.
%% Cell type:code id:07f67cfb-3edd-4160-a42e-679f97fedbc8 tags:
``` python
assert has_self_loop(g)
```
%% Cell type:markdown id:be1da5d3-b677-41dc-b52a-428e84e834ed tags:
## Exercise 5: Use embedded marking for visited nodes
Instead of using an external list to store visited node, use the data structure below that stores the information internally.
%% Cell type:code id:fb11aa28-e1a8-4700-99a6-c7f0e8477be8 tags:
``` python
g2 = {
'a': {'neighbors': ['d'], 'visited': False},
'b': {'neighbors': ['c'], 'visited': False},
'c': {'neighbors': ['b', 'c', 'd', 'e'], 'visited': False},
'd': {'neighbors': ['a', 'c'], 'visited': False},
'e': {'neighbors': ['c'], 'visited': False},
'f': {'neighbors': [''], 'visited': False}
}
```
%% Cell type:code id:5bcb46e4-d175-4356-b33b-ff44ce7df2a1 tags:
``` python
def dfs2(graph, start_node):
stack = [start_node]
while stack:
node = stack.pop()
if not graph[node]['visited']:
print(node, end=' ')
graph[node]['visited'] = True
for neighbor in reversed(graph[node]['neighbors']):
if neighbor and not graph[neighbor]['visited']:
stack.append(neighbor)
dfs2(g2, 'a')
```
%% Cell type:code id:e4fcaef5-cfb0-4d10-a8ca-930696b29c89 tags:
``` python
# YOUR CODE HERE
raise NotImplementedError()
```
%% Cell type:markdown id:50882bb9-8de8-4e0a-93db-38aedfa77ca0 tags:
Write tests.
%% Cell type:code id:7fb9a85c-976f-4054-948a-a58d6e4504ea tags:
``` python
# YOUR CODE HERE
raise NotImplementedError()
```
%% Cell type:markdown id:ce9470d2-7b5c-48a9-9ebf-7060a023a379 tags:
## Exercise 6: Use a Graph POO data structure
Instead of using a Dict, use a POO class (that may use a dict internally) and associated methods to solve the above problems (as new methods of the class).
%% Cell type:code id:bcb18a5c-d96b-464e-aa14-bc096f1ecfd4 tags:
``` python
class Graph:
def __init__(self):
pass
def has_cycle(self):
pass
def is_connected(self):
pass
def has_self_loop(self):
pass
# YOUR CODE HERE
raise NotImplementedError()
```
%% Cell type:markdown id:5ad7b301-ef0f-431c-8587-9318d635c05b tags:
Write tests.
%% Cell type:code id:5d5fa858-9403-420d-a4e3-d00b90fd0d31 tags:
``` python
# YOUR CODE HERE
raise NotImplementedError()
```
%% Cell type:code id:c097160a-6c52-4caf-9e50-70688ae51106 tags:
``` python
```
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment