def traverse_graph(world): trail = Stack() visited = set() has_unexplored_paths = { world.starting_room.id } path = [] trail.push((None, world.starting_room)) # while there is at least one known room with paths that we have not traversed, keep traversing while len(has_unexplored_paths): current = trail.peek()[1] visited.add(current.id) # get every connecting room that we have not yet been to unvisited_neighbors = [n for n in get_neighbors(current) if n[1].id not in visited] # print(f'U_N: {[(n[0], n[1].id) for n in unvisited_neighbors]}') # this room has, at most, 1 neighbor that we have not yet visited. # therefore, everything about this room has been explored # this first 'if' is for tracking when the graph has been fully explored, not for traversing it if current.id in has_unexplored_paths and len(unvisited_neighbors) < 2: has_unexplored_paths.remove(current.id) # there is at least 1 neighbor of this room that we have not yet visited. # need to pick one and advance to it if len(unvisited_neighbors) > 0: # pick a neighbor direction, next_room = choice(unvisited_neighbors) # add it to the unexplored set (we haven't been yet, so we won't know if it has unexplored paths until we arrive) has_unexplored_paths.add(next_room.id) # add the direction to it to our traveral path path.append(direction) # add it to our backtracking trail # Yes, I unpacked a tuple just to repack it. No, I'm not sorry. trail.push((direction, next_room)) # there are no neighbors, or they have all been visited. # effectively, this is a dead end. go back to the previous room else: # figure out which way is backwards, and record it, and remove the current room from our 'trail' path.append(invert_dir(trail.pop()[0])) return path
class User: """ User class serves as an abstraction for users. Users are only allowed to shop at only one store. User instances are treated as regular users. """ ##### Part 4.1 ##### user_counter = 0 def __init__(self, name, store): """ Constructor for User instances. Each instance is initialized with the user's username and the store they shop at. Instance attributes are: name, store, balance, their user ID, purchase history, and shopping cart. """ # YOUR CODE GOES HERE # self.name = name self.store = store self.balance = 0 self.id = User.user_counter User.user_counter += 1 self.purchase_history = Stack() self.cart = Queue() self.store.add_user(self) def __str__(self): """ Return the string representation as: "standard user: {name} - {balance}$" """ # YOUR CODE GOES HERE # return "standard user: {} - {}$".format(self.name, self.balance) def __repr__(self): """ Return the string representation as: "USER<{id}>" """ # YOUR CODE GOES HERE # return "USER<{}>".format(self.id) def set_name(self, new_name): """ Replaces a user's old name to new_name """ # YOUR CODE GOES HERE # self.name = new_name def get_name(self): """ Returns the user's current name """ # YOUR CODE GOES HERE # return self.name def set_balance(self, amount): """ Set the user's current balance to the given amount """ # YOUR CODE GOES HERE # self.balance = amount def get_balance(self): """ Returns the user's current balance """ # YOUR CODE GOES HERE # return self.balance def add_balance(self, amount): """ Add the given amount to the current balance """ # YOUR CODE GOES HERE # self.balance += amount def last_purchase(self): """ Return the user's most recent purchase """ # YOUR CODE GOES HERE # return self.purchase_history.peek() def view_history(self): """ Print the user's entire purchase history """ # YOUR CODE GOES HERE # print(self.purchase_history) def view_cart(self): """ Print all items in the user's cart """ # YOUR CODE GOES HERE # print(self.cart) def clear_cart(self): """ Remove all items from the user's cart """ # YOUR CODE GOES HERE # self.cart = Queue() ##### Part 5.2 ##### def add_cart(self, product_id): """ Add the product with the given product id to the user's cart """ # YOUR CODE GOES HERE # item = self.store.get_product(product_id) if item == None: pass else: self.cart.enqueue(item) def checkout(self): """ Purchase all items in the user's cart and return a list of all purchased products. As soon as a product cannot be purchased, purchasing is stopped. Anything that was purchased successfully is returned in a list. """ # YOUR CODE GOES HERE # purchases = [] while not(self.cart.is_empty()): product = self.cart.peek() purchase = self.store.order(self.id, product.id) if purchase: self.cart.dequeue() purchases.append(purchase.product) self.purchase_history.push(purchase) else: break return purchases ##### Part 5.3 ##### def undo_purchase(self): """ Undo the user's most recent purchase. If there is no shopping history, print "USER: no purchase history" and do nothing else. Else, attempt to undo the purchase. If the store allows the request, remove that purchase from the user's purchase history. """ # YOUR CODE GOES HERE # if self.purchase_history.is_empty(): print("USER: no purchase history") else: last_purchase = self.purchase_history.peek() user = last_purchase.user user_id = user.id product = last_purchase.product request = self.store.undo_order(user_id, product) if request: user.purchase_history.pop()