def test_add_weight_no_edge(self): """ Test addting the weight of an edge that does not exist. """ g = Graph() g.add_node("A") g.add_node("B") with self.assertRaises(ValueError) as context: g.add_weight("A", "B", 1.51) self.assertIn("edge", str(context.exception))
def test_add_weight_invalid_start(self): """ Test addting the weight of an edge where the start node does not exist. """ g = Graph() g.add_node("A") g.add_node("B") with self.assertRaises(ValueError) as context: g.add_weight("C", "B", 20.00) self.assertIn("start", str(context.exception))
def test_add_weight_invalid_end(self): """ Test addting the weight of an edge where the end node does not exist. """ g = Graph() g.add_node("A") g.add_node("B") with self.assertRaises(ValueError) as context: g.add_weight("A", "C", 44.43) self.assertIn("end", str(context.exception))
def test_add_weight(self): """ Test updating the weight of an edge between two nodes. """ correct = "{'A': {'B': 3.14}, 'B': {}}" g = Graph() g.add_node("A") g.add_node("B") g.add_edge("A", "B") g.add_weight("A", "B", 3.14) self.assertEqual(str(g), correct)
class EvenSplit(): """ The EvenSplit class contains the code which handles adding people, transactions, and reducing the graph into the minimum number of transactions. """ def __init__(self): """ Construct a new EvenSplit instance. """ self.graph = Graph() def __str__(self): """ Return a string form of the EvenSplit object. This is the same as using the internal graph's __str__ function. """ return str(self.graph) def __repr__(self): """ Return a human-readable string form of the EvenSplit object. This is the same as using the internal graph's __repr__ function. """ return repr(self.graph) def add_person(self, name: str): """ Add a new person to the EvenSplit object. This adds a new node for the given name and connects it to all other nodes within the graph, excluding itself. """ if name is None: raise ValueError("Name cannot be None!") self.graph.add_node(name) for person in self.graph: if person != name: self.graph.add_edge(name, person) self.graph.add_edge(person, name) def add_transaction(self, name: str, amount: float): """ Add a transaction and evenly split the amount across all people. """ split_amount = amount / self.count() for person in self.graph: if person != name: self.graph.add_weight(person, name, split_amount) def count(self): """ Return the number of people in the graph. """ return self.graph.size() def read(self, i: IO[str] = stdin): """ Read in the people and their transactions and construct the graph with the input. """ num_users = int(next(i)) for _ in range(num_users): self.add_person(next(i).strip()) num_transactions = int(next(i)) for _ in range(num_transactions): line = next(i).split() self.add_transaction(line[0], float(line[1])) def print(self, out: IO[str] = stdout): """ Print the state of the split as transactions from one person to another. """ out.write("Here's how to get even:\n") for person in self.graph: for other in self.graph[person]: amount = "${:,.2f}".format(self.graph[person][other]) out.write(person + " pays " + other + " " + amount + "\n")