From 184c36a1561e4f4e35aa13f2c234c81b6be76ec3 Mon Sep 17 00:00:00 2001 From: rfamilara Date: Tue, 10 Nov 2020 22:31:38 -0600 Subject: [PATCH 1/5] Assigned data structures -Coded to add vertex to the graph -Coded for a directed edge to the graph --- projects/graph/graph.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/projects/graph/graph.py b/projects/graph/graph.py index 59fecae4b..b16afb14d 100644 --- a/projects/graph/graph.py +++ b/projects/graph/graph.py @@ -13,13 +13,19 @@ def add_vertex(self, vertex_id): """ Add a vertex to the graph. """ - pass # TODO + # This will hold the edges + 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: + # There's an edge from v1 to v2 + self.vertices[v1].add(v2) + else: + raise IndexError("nonexistent vert") def get_neighbors(self, vertex_id): """ From 8e974ce9be9aec12d3f849edea82128a66ed7301 Mon Sep 17 00:00:00 2001 From: rfamilara Date: Thu, 12 Nov 2020 20:56:52 -0600 Subject: [PATCH 2/5] Completed graph.py -Tests were successful --- projects/graph/graph.py | 159 +++++++++++++++++++++++++++++++++++++--- 1 file changed, 150 insertions(+), 9 deletions(-) diff --git a/projects/graph/graph.py b/projects/graph/graph.py index b16afb14d..c30d65bab 100644 --- a/projects/graph/graph.py +++ b/projects/graph/graph.py @@ -31,30 +31,83 @@ 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 + # Create an empty queue + q = Queue() + # Init: enqueue the starting node + q.enqueue(starting_vertex) + # Create a set to store visited nodes + visited = set() + # While the queue isn't empty + while q.size() > 0: + # Dequeue the first item + currentNode = q.dequeue() + # If it's not been visited: + if currentNode not in visited: + # Do something with the node + print(currentNode) + # Add all neighbors to the queue + visited.add(currentNode) + # Add all neighbors to the queue + for nextNode in self.get_neighbors(currentNode): + if nextNode not in visited: + q.enqueue(nextNode) def dft(self, starting_vertex): """ Print each vertex in depth-first order beginning from starting_vertex. """ - pass # TODO + # Create an empty stack + s = Stack() + # Create a set to store visited nodes + visited = set() + # Init: Push the starting node + s.push(starting_vertex) + # While the stack isn't empty + while s.size() > 0: + # Pop the first item + v = s.pop() + # If it's not been visited: + if v not in visited: + # Add all neighbors to the stack + visited.add(v) + # Do something with the node + print(v) + # Add all neighbors to the stack + for next_vert in self.get_neighbors(v): + s.push(next_vert) - def dft_recursive(self, starting_vertex): + 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 + # Add current node to visited + visited.add(starting_vertex) + # Print current node + print(starting_vertex) + # Save all current node neighbors to a variable + neighbors = self.get_neighbors(starting_vertex) + # While the current node has neighbors + while len(neighbors) > 0: + # For each neighnbor + for each in neighbors: + # If it has not been visited already + if each not in visited: + # Rerun the function, replacing the current node with the neighbor + self.dft_recursive(each, visited) + # If it has been visited + else: + return def bfs(self, starting_vertex, destination_vertex): """ @@ -62,7 +115,38 @@ def bfs(self, starting_vertex, destination_vertex): starting_vertex to destination_vertex in breath-first order. """ - pass # TODO + # Create empty queue + q = Queue() + # Enqueue the starting node + q.enqueue([starting_vertex]) + # Create a set for visited vertices + visited = set() + # While queue is not empty + while q.size() > 0: + # Create current path variable set to first node in q + currentPath = q.dequeue() + # Set the last node in the currentPath to a variable + lastNode = currentPath[-1] + # If it hasnt been visited + if lastNode not in visited: + # Check if it is the destination + if lastNode == destination_vertex: + # Return the path if it is + return currentPath + # If it is not the target + else: + # Add the lastNode to visited + visited.add(lastNode) + # Set the lastNode neighbors to variable + neighbors = self.get_neighbors(lastNode) + # For each of lastNodes neighbors + for neighbor in neighbors: + # Copy the path current path + copy = currentPath[:] + # Add the neighbor + copy.append(neighbor) + # Add the copy to the q + q.enqueue(copy) def dfs(self, starting_vertex, destination_vertex): """ @@ -70,9 +154,40 @@ def dfs(self, starting_vertex, destination_vertex): starting_vertex to destination_vertex in depth-first order. """ - pass # TODO + # Create empty stack + s = Stack() + # Push the starting node + s.push([starting_vertex]) + # Create a set for visited vertices + visited = set() + # While stack is not empty + while s.size() > 0: + # Create current path variable set to first node in s + currentPath = s.pop() + # Set the last node in the currentPath to a variable + lastNode = currentPath[-1] + # If it hasnt been visited + if lastNode not in visited: + # Check if it is the destination + if lastNode == destination_vertex: + # Return the path if it is + return currentPath + # If it is not the target + else: + # Add the lastNode to visited + visited.add(lastNode) + # Set the lastNode neighbors to variable + neighbors = self.get_neighbors(lastNode) + # For each of lastNodes neighbors + for neighbor in neighbors: + # Copy the path current path + copy = currentPath[:] + # Add the neighbor + copy.append(neighbor) + # Add the copy to the s + s.push(copy) - def dfs_recursive(self, starting_vertex, destination_vertex): + def dfs_recursive(self, starting_vertex, destination_vertex, path=Stack(), visited=set()): """ Return a list containing a path from starting_vertex to destination_vertex in @@ -80,7 +195,33 @@ def dfs_recursive(self, starting_vertex, destination_vertex): This should be done using recursion. """ - pass # TODO + # Create a path, this will be None the first time this function runs + currentPath = path.pop() + # If currentPath is None + if currentPath == None: + # Make currentPath the starting vertex + currentPath = [starting_vertex] + # Check if the last node in the currentPath is not in visited + if currentPath[-1] not in visited: + # Add the last node to visited + visited.add(currentPath[-1]) + # For each of the last nodes neighbors + for neighbor in self.get_neighbors(currentPath[-1]): + # If the neighbor is the destination + if neighbor == destination_vertex: + # Append that neighbor to the currentPath + currentPath.append(neighbor) + # Return the currentPath + return currentPath + # Create a copy of the currentPath + copy = currentPath.copy() + # Add the neighbor to the copy + copy.append(neighbor) + # Push the copy to the reoccuring path + path.push(copy) + # Rerun the function with updated values + return self.dfs_recursive(starting_vertex, destination_vertex, path, visited) + if __name__ == '__main__': graph = Graph() # Instantiate your graph From 7561b7c43c62656a15ea4ad0808c9855716f88f1 Mon Sep 17 00:00:00 2001 From: rfamilara Date: Sun, 15 Nov 2020 21:04:38 -0600 Subject: [PATCH 3/5] Completed ancestor.py -Tests were successful --- projects/ancestor/ancestor.py | 36 ++++++++++++++++++++++++++++++++++- projects/ancestor/util.py | 28 +++++++++++++++++++++++++++ 2 files changed, 63 insertions(+), 1 deletion(-) create mode 100644 projects/ancestor/util.py diff --git a/projects/ancestor/ancestor.py b/projects/ancestor/ancestor.py index 3bd003098..5d8157c5f 100644 --- a/projects/ancestor/ancestor.py +++ b/projects/ancestor/ancestor.py @@ -1,3 +1,37 @@ +from util import Stack, Queue def earliest_ancestor(ancestors, starting_node): - pass \ No newline at end of file + # Create an empty queue + q = Queue() + # Create an list called 'path' housing the starting_node + path = [starting_node] + # Add that path(just the starting_node) to the queue + q.enqueue(path) + # While the queue is not empty + while q.size() > 0: + # Create a currentPath variable set to be our dequeued queue + currentPath = q.dequeue() + # Create an empty newPath list + newPath = [] + # Create a changed variable set to False + changed = False + # Loop over each node in the currentPath + for node in currentPath: + # Loop through its ancestors + for ancestor in ancestors: + # If the value of the next ancestor is equal to the node: + if ancestor[1] == node: + # Append the current ancestor to the newPath + newPath.append(ancestor[0]) + # Set its changed value to true + changed = True + # Add the new path to the queue + q.enqueue(newPath) + # If changed is False + if changed is False: + # If it has no parents + if currentPath[0] == starting_node: + return -1 + # If it does return it + else: + return currentPath[0] \ No newline at end of file diff --git a/projects/ancestor/util.py b/projects/ancestor/util.py new file mode 100644 index 000000000..f757503fb --- /dev/null +++ b/projects/ancestor/util.py @@ -0,0 +1,28 @@ + +# Note: This Queue class is sub-optimal. Why? +class Queue(): + def __init__(self): + self.queue = [] + def enqueue(self, value): + self.queue.append(value) + def dequeue(self): + if self.size() > 0: + return self.queue.pop(0) + else: + return None + def size(self): + return len(self.queue) + +class Stack(): + def __init__(self): + self.stack = [] + 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) + From bb8e50ec9b2ec5ec0e3e9281d9abe31965e66b2d Mon Sep 17 00:00:00 2001 From: rfamilara Date: Tue, 17 Nov 2020 20:40:21 -0600 Subject: [PATCH 4/5] Completed Social Graph Code for social.py completed Tests were successful --- projects/social/social.py | 61 ++++++++++++++++++++++++++++++++++----- 1 file changed, 53 insertions(+), 8 deletions(-) diff --git a/projects/social/social.py b/projects/social/social.py index 8609d8800..882f45899 100644 --- a/projects/social/social.py +++ b/projects/social/social.py @@ -1,3 +1,24 @@ +import random +import math + +class Queue(): + def __init__(self): + self.queue = [] + + def __repr__(self): + return str(self.queue) + + def enqueue(self, value): + self.queue.append(value) + def dequeue(self): + if self.size() > 0: + return self.queue.pop(0) + else: + return None + def size(self): + return len(self.queue) + + class User: def __init__(self, name): self.name = name @@ -32,36 +53,60 @@ 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 + posible_friendships = [] + # Add users + for i in range(0, num_users): + self.add_user(f'User {i}') + + for user_id in self.users: # Create friendships + for friend_id in range(user_id + 1, self.last_id + 1): + posible_friendships.append((user_id, friend_id)) + + random.shuffle(posible_friendships) + for i in range(0, math.floor(num_users * avg_friendships / 2)): + friendship = posible_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 - Returns a dictionary containing every user in that user's extended network with the shortest friendship path between them. - 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 + # crawl using a queue + queue = Queue() + # start with the staring id in the queue + queue.enqueue([user_id]) + # keep track of what friends and friends of friends we visited + visited = dict() + while queue.size() > 0: + current_path = queue.dequeue() + # print(f'Current path: {current_path}') + # pop off the last element in queue and declare that the path + current_user_id = current_path[-1] + if current_user_id not in visited: + # mark current user visited key is current user and value is path + # we use a dictionary to store the key of the user_id we are searching and the value is the path of how we get to that friend + visited[current_user_id] = current_path + for friend in self.friendships[current_user_id]: + newPath = list(current_path) + newPath.append(friend) + queue.enqueue(newPath) return visited - if __name__ == '__main__': sg = SocialGraph() sg.populate_graph(10, 2) From 3c22343512a0786ca52a20bfe6f374f58ce280cd Mon Sep 17 00:00:00 2001 From: rfamilara Date: Thu, 19 Nov 2020 20:55:16 -0600 Subject: [PATCH 5/5] Completed adv,py Tests Passed --- projects/adventure/adv.py | 73 ++++++++++++++++++++++++++++++++++----- 1 file changed, 64 insertions(+), 9 deletions(-) diff --git a/projects/adventure/adv.py b/projects/adventure/adv.py index 8bc540b5e..0ff78bf1a 100644 --- a/projects/adventure/adv.py +++ b/projects/adventure/adv.py @@ -29,6 +29,61 @@ # traversal_path = ['n', 'n'] traversal_path = [] +# Create an empty dictionary to save all the visited rooms +visited = {} +# Create an empty list that will save your reverse path, allowing you to backtrack when neccesary +backtrackPath = [] +# Save all possible movement options as keys, with their opposite directions as values +movementOptions = {'n': 's', 's': 'n', 'w': 'e', 'e': 'w'} +# Saves the current room (Room Number) in visited as a key, with each possible exit DIRECTION as values +visited[player.current_room.id] = player.current_room.get_exits() + +# While not every room has been explored... +while len(visited) < len(room_graph): + + # If the current room has not been visited... + # Save it as visited, check off where you came from, and see where you can go now + if player.current_room.id not in visited: + # Saves the current room in visited as a key (ROOM NUMBER), with each possible exit as values (DIRECTIONS) + visited[player.current_room.id] = player.current_room.get_exits() + # Saves the last direction in backtrackPath as the previousRoom + previousRoom = backtrackPath[-1] + print("previousRoom(Checking Rooms Case): ", previousRoom) + print("backtrackPath: ", backtrackPath) + print("Currently in: ", player.current_room.id) + # Remove the direction you just came from as a possible exit + visited[player.current_room.id].remove(previousRoom) + + elif len(visited[player.current_room.id]) > 0: + # Save the last of the current rooms exits as a variable + nextRoom = visited[player.current_room.id][-1] + print("nextRoom: ", nextRoom) + print("backtrackPath: ", backtrackPath) + print("Currently in: ", player.current_room.id) + # Remove that nextRoom from the current rooms exits + visited[player.current_room.id].pop() + # Add that to the answer path + traversal_path.append(nextRoom) + # Add the reverse movement to backtrackPath to keep track of where you're going! + backtrackPath.append(movementOptions[nextRoom]) + # Go into that next room + player.travel(nextRoom) + print("Walking to:", nextRoom) + + elif len(visited[player.current_room.id]) == 0: + # Save the direction you just came from as the previous room + previousRoom = backtrackPath[-1] + print("previousRoom(Backtracking Case): ", previousRoom) + print("backtrackPath: ", backtrackPath) + print("Currently in: ", player.current_room.id) + # Remove that direction from the backtrackPath + backtrackPath.pop() + # Add that to the answer path + traversal_path.append(previousRoom) + # Go back to the previous room + player.travel(previousRoom) + print("Walking BACK to:", previousRoom) + # TRAVERSAL TEST @@ -51,12 +106,12 @@ ####### # UNCOMMENT TO WALK AROUND ####### -player.current_room.print_room_description(player) -while True: - cmds = input("-> ").lower().split(" ") - if cmds[0] in ["n", "s", "e", "w"]: - player.travel(cmds[0], True) - elif cmds[0] == "q": - break - else: - print("I did not understand that command.") +#player.current_room.print_room_description(player) +#while True: +# cmds = input("-> ").lower().split(" ") +# if cmds[0] in ["n", "s", "e", "w"]: +# player.travel(cmds[0], True) +# elif cmds[0] == "q": +# break +# else: +# print("I did not understand that command.")