diff --git a/projects/ancestor/ancestor.py b/projects/ancestor/ancestor.py index 3bd003098..ffee2dcc3 100644 --- a/projects/ancestor/ancestor.py +++ b/projects/ancestor/ancestor.py @@ -1,3 +1,40 @@ +from collections import deque, defaultdict + def earliest_ancestor(ancestors, starting_node): - pass \ No newline at end of file + graph = create_graph(ancestors) + stack = deque() + paths = [] + + stack.append([starting_node]) + + while len(stack): + current_path = stack.pop() + current_vertex = current_path[-1] + + if current_vertex in graph: + for neighbor in graph[current_vertex]: + new_path = list(current_path) + new_path.append(neighbor) + stack.append(new_path) + elif current_vertex != starting_node: + if not len(paths): + paths.append(current_path) + elif len(current_path) > len(paths[0]) or ( + len(current_path) == len(paths[0]) and current_path[-1] < paths[0][-1] + ): + paths = [current_path] + + return paths[0][-1] if len(paths) else -1 + +def create_graph(edges): + + graph = defaultdict(set) + for edge in edges: + ancestor, child = edge[0], edge[1] + graph[child].add(ancestor) + return graph + + + + diff --git a/projects/graph/graph.py b/projects/graph/graph.py index 59fecae4b..d39544132 100644 --- a/projects/graph/graph.py +++ b/projects/graph/graph.py @@ -2,7 +2,7 @@ Simple graph implementation """ from util import Stack, Queue # These may come in handy - +from collections import deque class Graph: """Represent a graph as a dictionary of vertices mapping labels to edges.""" @@ -13,42 +13,82 @@ def add_vertex(self, vertex_id): """ Add a vertex to the graph. """ - pass # TODO + self.vertices[vertex_id] = set() def add_edge(self, v1, v2): """ Add a directed edge to the graph. """ - pass # TODO - + if v1 not in self.vertices or v2 not in self.vertices: + print(' Can not add edges to vertices that do not exist') + else: + self.vertices[v1].add(v2) def get_neighbors(self, vertex_id): """ Get all neighbors (edges) of a vertex. """ - pass # TODO + return self.vertices[vertex_id] def bft(self, starting_vertex): """ Print each vertex in breadth-first order beginning from starting_vertex. """ - pass # TODO + + queue = deque() + queue.append(starting_vertex) + visited = set() + + while len(queue): + current_vertex = queue.popleft() + if current_vertex not in visited: + visited.add(current_vertex) + print(current_vertex) + for neighbor in self.get_neighbors(current_vertex): + queue.append(neighbor) + + + def dft(self, starting_vertex): """ Print each vertex in depth-first order beginning from starting_vertex. """ - pass # TODO + stack = deque() + stack.append(starting_vertex) + visited = set() - def dft_recursive(self, starting_vertex): + while len(stack): + current_vertex = stack.pop() + if current_vertex not in visited: + print(current_vertex) + visited.add(current_vertex) + for neighbor in self.get_neighbors(current_vertex): + stack.append(neighbor) + + + def dft_recursive(self, starting_vertex, visited = None): """ Print each vertex in depth-first order beginning from starting_vertex. This should be done using recursion. """ - pass # TODO + + # create a visited + # if start isnt in visited add it + # print start + # call recursive funciton for neighbors of vertix using neighbor and visited + + if not visited: + visited = set() + + if starting_vertex not in visited: + visited.add(starting_vertex) + print(starting_vertex) + for neighbor in self.get_neighbors(starting_vertex): + self.dft_recursive(neighbor, visited) def bfs(self, starting_vertex, destination_vertex): """ @@ -56,7 +96,23 @@ def bfs(self, starting_vertex, destination_vertex): starting_vertex to destination_vertex in breath-first order. """ - pass # TODO + queue = deque() + visited = set() + queue.append([starting_vertex]) + + while len(queue): + current_path = queue.popleft() + current_vertex = current_path[-1] + + if current_vertex == destination_vertex: + return current_path + + if current_vertex not in visited: + visited.add(current_vertex) + for neighbor in self.get_neighbors(current_vertex): + new_path = list(current_path) + new_path.append(neighbor) + queue.append(new_path) def dfs(self, starting_vertex, destination_vertex): """ @@ -64,9 +120,25 @@ def dfs(self, starting_vertex, destination_vertex): starting_vertex to destination_vertex in depth-first order. """ - pass # TODO + queue = deque() + visited = set() + queue.append([starting_vertex]) + + while len(queue): + current_path = queue.pop() + current_vertex = current_path[-1] + + if current_vertex == destination_vertex: + return current_path + + if current_vertex not in visited: + visited.add(current_vertex) + for neighbor in self.get_neighbors(current_vertex): + new_path = list(current_path) + new_path.append(neighbor) + queue.append(new_path) - def dfs_recursive(self, starting_vertex, destination_vertex): + def dfs_recursive(self, starting_vertex, destination_vertex, visited = None, path = None): """ Return a list containing a path from starting_vertex to destination_vertex in @@ -74,7 +146,30 @@ def dfs_recursive(self, starting_vertex, destination_vertex): This should be done using recursion. """ - pass # TODO + # create a path + # path starts with starting vertex + # if starting vertex not in visited add to visited + # print vertex + # grab the neighbors of the vertex + + if not visited: + visited = set() + if not path: + path = [] + + visited.add(starting_vertex) + path = path + [starting_vertex] + + if starting_vertex == destination_vertex: + return path + + for neighbor in self.get_neighbors(starting_vertex): + if neighbor not in visited: + res = self.dfs_recursive(neighbor, destination_vertex, visited, path) + if res: + return res + return [] + if __name__ == '__main__': graph = Graph() # Instantiate your graph diff --git a/projects/social/social.py b/projects/social/social.py index 8609d8800..74fbf190e 100644 --- a/projects/social/social.py +++ b/projects/social/social.py @@ -1,3 +1,5 @@ +from collections import deque + class User: def __init__(self, name): self.name = name @@ -57,8 +59,19 @@ def get_all_social_paths(self, user_id): The key is the friend's ID and the value is the path. """ - visited = {} # Note that this is a dictionary, not a set - # !!!! IMPLEMENT ME + visited = {} + queue = deque() + queue.append([user_id]) + + while len(queue) > 0: + curr_Path = queue.popleft() + currNode = curr_Path[-1] + visited[currNode] = curr_Path + for friend in self.friendships[currNode]: + if friend not in visited: + new_path = curr_Path.copy() + new_path.append(friend) + queue.append(new_path) return visited