diff --git a/projects/ancestor/ancestor.py b/projects/ancestor/ancestor.py index 3bd003098..34272a579 100644 --- a/projects/ancestor/ancestor.py +++ b/projects/ancestor/ancestor.py @@ -1,3 +1,47 @@ +class Stack(): + def __init__( self ): + self.stack = [] -def earliest_ancestor(ancestors, starting_node): - pass \ No newline at end of file + def push( self, value ): + self.stack.append( value ) + + def pop( self ): + if self.size() > 0: + return self.stack.pop() + else: + return None + + def size( self ): + return len( self.stack ) + +def dfs( starting_vertex, graph ): + stack = Stack() + visited = [] + + stack.push( [ starting_vertex ] ) + + while stack.size(): + path = stack.pop() + node = path[ -1 ] + + if node not in visited: + visited.append( node ) + + for parent in graph.get( node, [] ): + stack.push( path + [ parent ] ) + + return visited[ -1 ] + +def earliest_ancestor( ancestors, starting_node ): + graph = {} + + for parent, child in ancestors: + if child not in graph: + graph[ child ] = [ parent ] + else: + graph[ child ].append( parent ) + + if starting_node not in graph: + return -1 + + return dfs( starting_node, graph )\ diff --git a/projects/graph/graph.py b/projects/graph/graph.py index 59fecae4b..719d858c4 100644 --- a/projects/graph/graph.py +++ b/projects/graph/graph.py @@ -13,42 +13,84 @@ 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 in self.vertices and v2 in self.vertices: + self.vertices[ v1 ].add( v2 ) + else: + raise LookupError( "Problem adding edge: Vertex not found" ) 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 + que = Queue() + visited = set() + + que.enqueue( starting_vertex ) + + while que.size(): + vert = que.dequeue() + + if vert not in visited: + visited.add( vert ) + + neighbors = self.get_neighbors( vert ) + for neighbor in neighbors: + que.enqueue( neighbor ) + + print( vert ) + def dft(self, starting_vertex): """ Print each vertex in depth-first order beginning from starting_vertex. """ - pass # TODO + stack = Stack() + visited = set() + + stack.push( starting_vertex ) + + while stack.size(): + vert = stack.pop() + + if vert not in visited: + visited.add( vert ) - def dft_recursive(self, starting_vertex): + neighbors = self.get_neighbors( vert ) + for neighbor in neighbors: + stack.push( neighbor ) + + print( vert ) + + def dft_recursive( self, starting_vertex, visited=set() ): """ Print each vertex in depth-first order beginning from starting_vertex. This should be done using recursion. """ - pass # TODO + print( starting_vertex ) + + visited.add( starting_vertex ) + + for neighbor in self.get_neighbors( starting_vertex ): + if neighbor not in visited: + visited.add( neighbor ) + + self.dft_recursive( neighbor, visited ) def bfs(self, starting_vertex, destination_vertex): """ @@ -56,7 +98,25 @@ def bfs(self, starting_vertex, destination_vertex): starting_vertex to destination_vertex in breath-first order. """ - pass # TODO + que = Queue() + visited = set() + + que.enqueue( [ starting_vertex ] ) + + while que.size(): + path = que.dequeue() + node = path[ -1 ] + + if node not in visited: + visited.add( node ) + + if node == destination_vertex: + return path + + for neighbor in self.get_neighbors( node ): + que.enqueue( path + [ neighbor ] ) + + return None def dfs(self, starting_vertex, destination_vertex): """ @@ -64,9 +124,27 @@ def dfs(self, starting_vertex, destination_vertex): starting_vertex to destination_vertex in depth-first order. """ - pass # TODO + stack = Stack() + visited = set() + + stack.push( [ starting_vertex ] ) + + while stack.size(): + path = stack.pop() + node = path[ -1 ] + + if node not in visited: + visited.add( node ) - def dfs_recursive(self, starting_vertex, destination_vertex): + if node == destination_vertex: + return path + + for neighbor in self.get_neighbors( node ): + stack.push( path + [ neighbor ] ) + + return None + + def dfs_recursive( self, starting_vertex, destination_vertex, visited=set(), path=[] ): """ Return a list containing a path from starting_vertex to destination_vertex in @@ -74,7 +152,28 @@ def dfs_recursive(self, starting_vertex, destination_vertex): This should be done using recursion. """ - pass # TODO + if path == []: + path = [ starting_vertex ] + + if starting_vertex not in visited: + visited.add( starting_vertex ) + + if starting_vertex == destination_vertex: + return path + + for neighbor in self.get_neighbors( starting_vertex ): + res = self.dfs_recursive( + neighbor, + destination_vertex, + visited, + path + [ neighbor ] + ) + + if res: + return res + + return None + if __name__ == '__main__': graph = Graph() # Instantiate your graph diff --git a/projects/social/social.py b/projects/social/social.py index 8609d8800..13fdfc100 100644 --- a/projects/social/social.py +++ b/projects/social/social.py @@ -1,3 +1,23 @@ +from random import shuffle + + +class Queue(): + def __init__( self ): + self.que = [] + + def enqueue( self, value ): + self.que.append( value ) + + def dequeue( self ): + if self.size() > 0: + return self.que.pop( 0 ) + else: + return None + + def size( self ): + return len( self.que ) + + class User: def __init__(self, name): self.name = name @@ -45,8 +65,22 @@ def populate_graph(self, num_users, avg_friendships): # !!!! IMPLEMENT ME # Add users + for u in range( num_users ): + self.add_user( u ) # Create friendships + friends = [] + + for uid in self.users: + for fid in range( uid + 1, self.last_id + 1 ): + friends.append( ( uid, fid ) ) + + shuffle( friends ) + + rng = num_users * avg_friendships // 2 + for i in range( rng ): + uid, fid = friends[ i ] + self.add_friendship( uid, fid ) def get_all_social_paths(self, user_id): """ @@ -59,6 +93,22 @@ def get_all_social_paths(self, user_id): """ visited = {} # Note that this is a dictionary, not a set # !!!! IMPLEMENT ME + que = Queue() + + que.enqueue( [ user_id ] ) + + while que.size(): + path = que.dequeue() + node = path[ -1 ] + + if node not in visited: + visited[ node ] = path + + friends = self.friendships[ node ] + + for friend in friends: + que.enqueue( path + [ friend ] ) + return visited