Skip to content

Day 1 #751

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open

Day 1 #751

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 26 additions & 1 deletion projects/ancestor/ancestor.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,28 @@

def earliest_ancestor(ancestors, starting_node):
pass
parent_child_dict = {}
for relationship in ancestors:
parent = relationship[0]
child = relationship[1]
if child not in parent_child_dict:
parent_child_dict[child] = set()
parent_child_dict[child].add(parent)

earliest_ancestor = -1

queue = []
queue.append(starting_node)
while len(queue) > 0:
curr_vertex = queue.pop()
if curr_vertex in parent_child_dict:
parent_with_lowest_ID = None
for parent in parent_child_dict[curr_vertex]:
if parent_with_lowest_ID is None:
parent_with_lowest_ID = parent
elif parent < parent_with_lowest_ID:
parent_with_lowest_ID = parent
queue.append(parent)
if parent_with_lowest_ID is not None:
earliest_ancestor = parent_with_lowest_ID

return earliest_ancestor
169 changes: 114 additions & 55 deletions projects/graph/graph.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"""
Simple graph implementation
"""
from util import Stack, Queue # These may come in handy
from collections import deque # These may come in handy

class Graph:

Expand All @@ -10,71 +10,124 @@ def __init__(self):
self.vertices = {}

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("Error: 1 or both vertices not found")
return
self.vertices[v1].add(v2)

def get_neighbors(self, vertex_id):
"""
Get all neighbors (edges) of a vertex.
"""
pass # TODO
if vertex_id not in self.vertices:
print(f"Error: id {vertex_id} not found")
return
return self.vertices[vertex_id]

def bft(self, starting_vertex):
"""
Print each vertex in breadth-first order
beginning from starting_vertex.
"""
pass # TODO
if starting_vertex not in self.vertices:
print(f"Error: {starting_vertex} not found")
return
discovered = set()
queue = deque()

queue.append(starting_vertex)
while len(queue) > 0:
curr_node = queue.popleft()
if curr_node not in discovered:
discovered.add(curr_node)
print(curr_node)
for neighbor in self.vertices[curr_node]:
queue.append(neighbor)

def dft(self, starting_vertex):
"""
Print each vertex in depth-first order
beginning from starting_vertex.
"""
pass # TODO

def dft_recursive(self, starting_vertex):
"""
Print each vertex in depth-first order
beginning from starting_vertex.
def dft(self, starting_vertex):
if starting_vertex not in self.vertices:
print(f"Error: {starting_vertex} not found")
return
discovered = set()
stack = []

stack.append(starting_vertex)
while len(stack) > 0:
curr_node = stack.pop()
if curr_node not in discovered:
discovered.add(curr_node)
print(curr_node)
for neighbor in self.vertices[curr_node]:
stack.append(neighbor)


def dft_recursive(self, selected_vertex, discovered=set()):
if selected_vertex not in self.vertices:
print(f"Error: {selected_vertex} not found")
return

discovered.add(selected_vertex)
print(selected_vertex)

for neighbor in self.vertices[selected_vertex]:
if neighbor not in discovered:
self.dft_recursive(neighbor, discovered)

This should be done using recursion.
"""
pass # TODO

def bfs(self, starting_vertex, destination_vertex):
"""
Return a list containing the shortest path from
starting_vertex to destination_vertex in
breath-first order.
"""
pass # TODO

def dfs(self, starting_vertex, destination_vertex):
"""
Return a list containing a path from
starting_vertex to destination_vertex in
depth-first order.
"""
pass # TODO

def dfs_recursive(self, starting_vertex, destination_vertex):
"""
Return a list containing a path from
starting_vertex to destination_vertex in
depth-first order.

This should be done using recursion.
"""
pass # TODO
queue = deque()
visited = set()
# push the current path you're on onto the stack, instead of just a single vertex
queue.append([starting_vertex])

while len(queue) > 0:
currPath = queue.popleft()
currNode = currPath[-1] # the current node you're on is the last node in the path
if currNode == destination_vertex:
return currPath
if currNode not in visited:
visited.add(currNode)
for neighbor in self.vertices[currNode]:
newPath = list(currPath) # make copy of current path
newPath.append(neighbor)
queue.append(newPath)

def dfs(self, starting_vertex, goal_vertex):
stack = []
visited = set()
# push the current path you're on onto the stack, instead of just a single vertex
stack.append([starting_vertex])

while len(stack) > 0:
currPath = stack.pop()
currNode = currPath[-1] # the current node you're on is the last node in the path
if currNode == goal_vertex:
return currPath
if currNode not in visited:
visited.add(currNode)
for neighbor in self.vertices[currNode]:
newPath = list(currPath) # make copy of current path
newPath.append(neighbor)
stack.append(newPath)

def dfs_recursive(self, starting_vertex, goal_vertex):
visited = set()
return self.dfs_recursive_helper([starting_vertex], visited, goal_vertex)

def dfs_recursive_helper(self, curr_path, visited, goal_vertex):
curr_vertex = curr_path[-1]
# base case if curr_vertex is goal_vertex, return path
if curr_vertex == goal_vertex:
return curr_path

visited.add(curr_vertex)
for neighbor in self.vertices[curr_vertex]:
if neighbor not in visited:
new_path = list(curr_path)
new_path.append(neighbor)
# recursive case - keep traversing the graph and visit the neighbor next
res = self.dfs_recursive_helper(new_path, visited, goal_vertex)
if len(res) > 0:
return res
# base case, return empty array if goal vertex not found
return []

if __name__ == '__main__':
graph = Graph() # Instantiate your graph
Expand Down Expand Up @@ -118,6 +171,7 @@ def dfs_recursive(self, starting_vertex, destination_vertex):
1, 2, 4, 3, 7, 6, 5
1, 2, 4, 3, 7, 5, 6
'''
print("breadth first traversal")
graph.bft(1)

'''
Expand All @@ -127,19 +181,24 @@ def dfs_recursive(self, starting_vertex, destination_vertex):
1, 2, 4, 7, 6, 3, 5
1, 2, 4, 6, 3, 5, 7
'''
print("depth first traversal")
graph.dft(1)
print("depth first traversal - recursive")
graph.dft_recursive(1)

'''
Valid BFS path:
[1, 2, 4, 6]
'''
print("breadth first search")
print(graph.bfs(1, 6))

'''
Valid DFS paths:
[1, 2, 4, 6]
[1, 2, 4, 7, 6]
'''
print("depth first search")
print(graph.dfs(1, 6))
print("depth first search - recursive")
print(graph.dfs_recursive(1, 6))