As a way to keep my skills fresh, I look for small jobs on Upwork that require python. Here is one of the job request I came across yesterday.

A tech company, Company X, with servers all over the world wanted to determine which two servers within a regional zone are closest to their web application users. Company X wants us to report back the name of cities that the servers are in and their IP addresses. Company X provided a dictionary object (see partial dict below, the full dict is provided at places.py) with pertinent information. The dictionary contains the city, ip address, coordinates, and zone for each server..

I challenge you to answer this question in your own way. Or, just follow along with how I approached it. More details about this exercise will be discussed below.

In [1]:
# Partial view of dictionary with client server information
PLACES = {
      "Amsterdam": {
        "IP": '208.65.255.10',
        "latitude": 52.370216,
        "longitude": 4.895168,
        "zone": ['1','2']
      },
      "Brussels": {
        "IP": '208.65.255.10',
        "latitude": 50.850346,
        "longitude": 4.351721,
        "zone": ['1','2','3']
      }}

Let's begin by pretending that I am a client of Company X. I live in Baltimore, MD and I spend all day on their new web app. I currently can not use the app because Company X is having technical issues. To fix this problem they have decided to route all web traffic to servers in Zone 1.

Company X wants its users to still have the fastest speed while connecting to the app thus they want to send each user's data to the closest city in Zone 1. Additionally, Company X requires redundacy, so they want us to report back the two closests cities.

Your company,PyTechGroup, was hired by Company X to fix this problem. How could we determine which cities I am closest to in Zone 1. My coordinates are (39.290385, -76.612189).

To solve this problem, Let's follow the steps below. Let's start with prerequisites, packages and imports.

Prequistes/packages

  1. I will be using python2.7
  2. We need to install geopy package. It will allow us to measure distance(miles) between cities.
  3. Import Statements
python --version
Python 2.7.13 :: Continuum Analytics, Inc
$ pip install geopy
from places import places
from geopy.distance import vincenty
from operator import itemgetter

A. Which cities are in Zone 1?

In this function(cities_in_zone) we are simply iterating through Company X's dictionary, pulling out the name of the cities in Zone 1, and appending the names to a list.

As a side note, some of the zones are overlapping, ie a city can exist in more than one zone.

In [3]:
def cities_in_zone(zone):
    ''' select cities by provided zone number
    zone: str; the zone which a city is designated to
    return: list
    '''
    cities = []
    for city, value in places.iteritems():
        if str(zone) in value['zone']:
            cities.append(city)
    return cities

B. What is the distance between each Zone 1 city and me?

The next step is for us to determine the distance between me and each city in Zone 1. In the 'closest_cities'function, we input my location and the city coordinates into geopy's vincenty function to derive the distance in miles. Next, we append the city's name and distance to a list.

STOP: USELESS INFO: Vincenty is a highly accurate method for measuring distances, unlike other methods, its accuracy doesn't depend on your location.

In [4]:
def closest_cities(lat, lgt, zone, num=2):
    ''' Find cities closest to designated location within a zone
    lat: float; latitude
    lgt: float; longitude
    zone: str; the zone which a city is designated to
    num: int, the number of cities that should be designated as closest
    '''
    dist = []
    start = (lat,lgt)
    cities = cities_in_zone(zone)
    for city in cities:
        distance = vincenty(start, (places[city]['latitude'], places[city]['longitude']))
        dist.append((city, distance.miles))
    final = find_min_distances(dist, num)
    return final

C. Which two cities in Zone 1 are closest to me?

In the previous function "find_min_distances" was called to find the smallest distance between a city and me. "find_min_distances" takes two arguments. Firstly, a list of lists containing the city names and their distances from me. Secondly, an integer that specifies how many cities to return to Company X.

The output from "find_min_distances" is a dict with the city name as the key and its IP address as a value. It is returned as a dict simply because Company X wanted the answer as a dict object.

In [5]:
def find_min_distances(distances, numbers):
    ''' From the calculated geo distances find the smallest
    distances: list; list containing city name and distance value in miles
    numbers: int; the number of cities to return
    return: dict
    '''
    final = {}
    if numbers > len(distances):
        numbers = len(distances)
    for num in range(numbers):
        b = min([x[1] for x in enumerate(distances)], key=itemgetter(1))
        final[b[0]] = {'IP':places[b[0]]['IP']}
        distances.remove(b)
    return final

Finally, which cities are closest to Baltimore?

In [6]:
closest_cities(39.285879, -76.550419, 2)
Out[6]:
{'London': {'IP': '208.65.255.10'}, 'Madrid': {'IP': '208.65.255.10'}}

Now it is your turn! Can you figure out a better or faster way to answer this question?

Related content