Skip to content

initial commit #745

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 4 commits into
base: master
Choose a base branch
from
Open
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
5 changes: 5 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"cSpell.words": [
"deque"
]
}
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Graphs

# initial commit [ https://github.com/LambdaSchool/Graphs/pull/745 ]
## Objectives

* [Graph Intro](objectives/graph-intro)
Expand Down
36 changes: 35 additions & 1 deletion projects/ancestor/ancestor.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,37 @@
from collections import deque, defaultdict

def earliest_ancestor(ancestors, starting_node):
pass
#child pair with no parent
graph = create_graph(ancestors)
stack = deque()
stack.append((starting_node, 0)) # distance from node
visited = set()
earliestAncestor = (starting_node, 0)

while len(stack) > 0:
current = stack.pop()
current_node, distance = current[0], current[1]
visited.add(current)

if current_node not in graph:
if distance > earliestAncestor[1]:
earliestAncestor = current
elif distance == earliestAncestor[1] and current_node < earliestAncestor[0]:
earliestAncestor = current
else:
for ancestor in graph[current_node]:
if ancestor not in visited:
stack.append((ancestor, distance + 1))

return earliestAncestor[0] if earliestAncestor[0] != starting_node else -1


def create_graph(edges):
# every added dict should a deafult value set()
graph = defaultdict(set)

for edge in edges:
ancestor, child = edge[0], edge[1]
graph[child].add(ancestor)

return graph
104 changes: 92 additions & 12 deletions projects/graph/graph.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,68 +13,148 @@ 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
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
visited = []
queue = Queue()
queue.enqueue(starting_vertex)

while queue.size() > 0:
current_node = queue.dequeue()
if current_node not in visited:
visited.append(current_node)
print(current_node)
for neighbor in self.get_neighbors(current_node):
queue.enqueue(neighbor)


def dft(self, starting_vertex):
"""
Print each vertex in depth-first order
beginning from starting_vertex.
"""
pass # TODO
visited = []
stack = Stack()
stack.push(starting_vertex)

while stack.size() > 0:
current_node = stack.pop()
if current_node not in visited:
visited.append(current_node)
print(current_node)
for neighbor in self.get_neighbors(current_node):
stack.push(neighbor)


def dft_recursive(self, starting_vertex):
"""
Print each vertex in depth-first order
beginning from starting_vertex.

This should be done using recursion.
"""
pass # TODO
visited = set()
return self.dft_recursive_helper(starting_vertex, visited)

def dft_recursive_helper(self, starting_vertex, visited):
visited.add(starting_vertex)
print(starting_vertex)
for neighbor in self.get_neighbors(starting_vertex):
if neighbor not in visited:
self.dft_recursive_helper(neighbor, visited)

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
visited = set()
queue = Queue()
queue.enqueue([starting_vertex])

while queue.size() > 0:
current_path = queue.dequeue()
current_node = current_path[-1]

if current_node == destination_vertex:
return current_path

if current_node not in visited:
visited.add(current_node)
for neighbor in self.get_neighbors(current_node):
new_path = list(current_path)
new_path.append(neighbor)
queue.enqueue(new_path)


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
visited = set()
stack = Stack()
stack.push([starting_vertex])

while stack.size() > 0:
current_path = stack.pop()
current_node = current_path[-1]

if current_node == destination_vertex:
return current_path

if current_node not in visited:
visited.add(current_node)
for neighbor in self.get_neighbors(current_node):
new_path = list(current_path)
new_path.append(neighbor)
stack.push(new_path)

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
visited = set()
return self.dfs_recursive_helper([starting_vertex], destination_vertex, visited)

def dfs_recursive_helper(self, current_path, destination_vertex, visited):
current_vertex = current_path[-1]

if current_vertex == destination_vertex:
return current_path

visited.add(current_vertex)

for neighbor in self.get_neighbors(current_vertex):
if neighbor not in visited:
new_path = list(current_path)
new_path.append(neighbor)
result = self.dfs_recursive_helper(new_path, destination_vertex, visited)
if len(result) > 0:
return result

return []

if __name__ == '__main__':
graph = Graph() # Instantiate your graph
Expand Down Expand Up @@ -142,4 +222,4 @@ def dfs_recursive(self, starting_vertex, destination_vertex):
[1, 2, 4, 7, 6]
'''
print(graph.dfs(1, 6))
print(graph.dfs_recursive(1, 6))
print(graph.dfs_recursive(1, 6))
52 changes: 34 additions & 18 deletions projects/social/social.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
import random, math
from collections import deque

class User:
def __init__(self, name):
self.name = name

class SocialGraph:
def __init__(self):
self.last_id = 0
self.users = {}
self.friendships = {}
self.users = {}
self.friendships = {}

def add_friendship(self, user_id, friend_id):
"""
Expand All @@ -24,47 +27,60 @@ def add_user(self, name):
"""
Create a new user with a sequential integer ID
"""
self.last_id += 1 # automatically increment the ID to assign the new user
self.last_id += 1 #increment the ID to assign the new user
self.users[self.last_id] = User(name)
self.friendships[self.last_id] = set()

def populate_graph(self, num_users, avg_friendships):
"""
Takes a number of users and an average number of friendships
as arguments

Creates that number of users and a randomly distributed friendships
between those users.

The number of users must be greater than the average number of friendships.
"""
# Reset graph
self.last_id = 0
self.users = {}
self.friendships = {}
# !!!! IMPLEMENT ME

# Add users
for i in range(num_users):
self.add_user(f"User {i}")

# Create friendships
possible_friendships = []
for user_id in self.users:
for friend_id in range(user_id + 1, self.last_id+ 1):
possible_friendships.append((user_id, friend_id))

random.shuffle(possible_friendships)

for i in range(math.floor(num_users * avg_friendships / 2)):
friendship = possible_friendships[i]
self.add_friendship(friendship[0], friendship[1])

def get_all_social_paths(self, user_id):
"""
Takes a user's user_id as an argument
# dict mapping
visited = {}
queue = deque()
queue.append([user_id])

Returns a dictionary containing every user in that user's
extended network with the shortest friendship path between them.
while len(queue) > 0:
current_path = queue.popleft()
current_node = current_path[-1]
visited[current_node] = current_path

for friend in self.friendships[current_node]:
if friend not in visited:
new_path = current_path.copy()
new_path.append(friend)
queue.append(new_path)

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
return visited


if __name__ == '__main__':
sg = SocialGraph()
sg.populate_graph(10, 2)
print(sg.friendships)
print(f"friendships: {sg.friendships}")
connections = sg.get_all_social_paths(1)
print(connections)
print(f"connections: {connections}")