Example #1
0
    def _num_trips(self, node_from, node_to, minimum, maximum, is_distance):
        """
        Determines the number of trips that can be made between two points
            within a certain number of moves, or less than a certain
            distance.

        Arguments:
            node_from - The origin point of the connection being queried.
                Method throws a ValueError if the node does not exist.
            node_to - The destination of the connection being queried.
                Method throws a ValueError if the node does not exist.
            minimum - The minimum moves/distance required to be made before
                trips are counted. Method will throw a ValueError if less
                than zero.
            maximum - The maximum moves/distance until the number of trips
                stop being counted and the method exits. Will throw a
                ValueError if less than minimum.
            is_distance - Whether or not we're calculating the number of trips
                possible based on distance (True) or number of moves (False).
        Returns:
            int - The number of possible trips given the restrictions.
        """
        if maximum < minimum:
            raise ValueError("maximum ({:d}) is less than " \
                    "minimum ({:d})".format(maximum, minimum))
        elif minimum <= 0:
            raise ValueError("minimum requires a value greater than zero")
        if self.get(node_from) is None or self.get(node_to) is None:
            raise ValueError("Non-existant origin or destination node was " \
                    "given")
        available_routes = 0

        # We start by building a priority queue made of tuples, which contains
        # origin node and the number of moves or distance needed to get there.
        # Then, we start populating the queue with the
        # name of connecting nodes and the number of connections traversed
        # or distance traversed to get from the origin to that point.
        trip_queue = PriorityQueue()
        trip_queue.add((0, node_from))
        while not trip_queue.is_empty():
            current_node = trip_queue.remove()
            # leave the loop now if we've reached the maximum.
            # in the current data set, our maximum move count limit is based
            # on being less than OR EQUAL TO the maximum, while the distance
            # limit is based on being LESS THAN to the maximum ONLY. That
            # conditional is reflected here.
            if is_distance and current_node[0] >= maximum:
                break
            elif not is_distance and current_node[0] > maximum:
                break
            # add to the count if we've reached the destination and
            # we're above our minimum
            if current_node[1] == node_to and current_node[0] >= minimum:
                available_routes += 1
            # continue adding to the queue - if we're measuring by distance,
            # add the distance to the next node. Else, just increment by one
            # and keep going.
            for connected_node, distance in self.get(current_node[1]).items():
                if is_distance:
                    increment = distance
                else:
                    increment = 1
                trip_queue.add((current_node[0] + increment, connected_node))

        return available_routes
Example #2
0
    def min_route_distance(self, node_from, node_to):
        """
        Gets the shortest route between two points, using Dijkstra's
            algorithm. This version is modified to allow for a route that
            traverses back to the origin if such a route is possible.

        Arguments:
            node_from - The origin point of the connection being queried.
                Method throws a ValueError if the node does not exist.
            node_to - The destination of the connection being queried.
                Method throws a ValueError if the node does not exist.

        Returns:
            int/float - The minimum distance to traverse to complete the
                shortest possible route. If the route is origin to origin
                and no path can be made that traverses other routes to get
                back to the origin, 0 is returned. If it is impossible to get
                from the origin to the destination when the two are different,
                float("inf") (i.e. infinity) is returned.
        """
        if self.get(node_from) is None or self.get(node_to) is None:
            raise ValueError("Non-existant origin or destination node was " \
                    "given")

        min_distances = {}
        node_queue = PriorityQueue()

        # First, initialize min_distances with assumed min_distances for
        # the time being (i.e. 0 for origin, float("inf") for all possible
        # destinations
        for key in self._nodes.keys():
            if key == node_from:
                init_minimum = 0
            else:
                init_minimum = float("inf")
            min_distances[key] = init_minimum
            # Items in the priority queue are tuples, with the min_distance
            # listed first for sorting, then the key of the final point
            node_queue.add((init_minimum, key))

        while not node_queue.is_empty():
            minimum, current_node = node_queue.remove()
            for connected_node, connected_distance in self.get(
                    current_node).items():
                new_distance = minimum + connected_distance
                # If the minimum distance from here plus the distance to the
                # next node is less than the current minimum distance to that
                # node from the origin, replace it
                # OR - if the distance is the origin (i.e. min_distance
                # from origin to connected_node is zero) - this allows us to
                # loop back to the origin!
                if new_distance < min_distances[connected_node] or \
                        min_distances[connected_node] == 0:
                    min_distances[connected_node] = new_distance
                    # Prevents the origin node from being added back into the
                    # queue, so we don't re-evaluate the whole graph again
                    if not connected_node == node_from:
                        node_queue.add((new_distance, connected_node))

        # Now we have a dict of all of the Dijkstra min distances to
        # those points from the origin -- we want to return the distance
        # to just one point (the destination)
        return min_distances[node_to]
Example #3
0
from queues import PriorityQueue

class Golfer:
	def __init__(self, name, score):
		self.name = name
		self.score = score

	def __str__(self):
		return "{0:16}: {1}".format(self.name, self.score)

	def __gt__(self, other):
		return self.score < other.score # less is more


tiger = Golfer("Tiger Woods", 61)
phil = Golfer("Phil Mickelson", 72)
hal = Golfer("Hal Sutton", 69)

pq = PriorityQueue()
for g in [tiger, phil, hal]:
	pq.insert(g)

while not pq.is_empty():
	print(pq.remove())