Food Truck IEEEXtreme 10.0

over 3 years ago.

As cited in the description this problem was proposed by Nokia so I thought it will be hard however it was one of the easiest problems in the IEEEXtreme 10.

The problem consist of finding subscribers in radius r of a given GPS coordinate.

The information about the subscribers are given in the form

Date&Time,Latitude,Longitude,PhoneNumber
10/21/2016 13:34,18.912875,72.822318,9020320100
10/21/2016 10:35,18.9582233,72.8275845,9020320024
10/21/2016 15:20,18.95169982,72.83525604,9020320047
......

First we need to read the data then parse the date&time. For that I used datetime library in python and with little help from strftime the job is done

In [132]: from datetime import datetime

In [133]: datetime.strptime("10/21/2016 13:34", "%m/%d/%Y %H:%M")
Out[133]: datetime.datetime(2016, 10, 21, 13, 34)

Then I used Haversine formula to calculate the distance between two GPS points.

from math import radians, cos, sin, asin, sqrt

def haversine(lon1, lat1, lon2, lat2):
    """
    Calculate the great circle distance between two points 
    on the earth (specified in decimal degrees)
    """
    # convert decimal degrees to radians 
    lon1, lat1, lon2, lat2 = map(radians, [lon1, lat1, lon2, lat2])

    # haversine formula 
    dlon = lon2 - lon1 
    dlat = lat2 - lat1 
    a = sin(dlat/2)**2 + cos(lat1) * cos(lat2) * sin(dlon/2)**2
    c = 2 * asin(sqrt(a)) 
    r = 6378.137 
    return c * r

Then I created a empty dictionary with the subscriber's phone as the key and for the value [date, distance] . Then read line by line if the line I found is a newer position of the subscriber replace the date and distance.

d = {}
for line in sys.stdin:
    subscriber  = line.strip().split(",")

    dat = datetime.strptime(subscriber[0], "%m/%d/%Y %H:%M")
    h = haversine(lon, lat, float(subscriber[2]), float(subscriber[1]))
    if item[3] in d:
        if dat > d[subscriber[3]][0]:
            d[subscriber[3]] = [dat, h]
    else:
        d[item[3]] = [dat, h]

Finally all I need to do is to check if the distance is less than the given radius. then just print the sorted phone numbers .

res = []
for phone in d:
    if  d[phone][1]<=r:
        res.append(phone)

print ",".join([phone for phone in sorted(res)])

The complete code:

from datetime import datetime
from math import radians, cos, sin, asin, sqrt
import sys

def haversine(lon1, lat1, lon2, lat2):
    """
    Calculate the great circle distance between two points 
    on the earth (specified in decimal degrees)
    """
    # convert decimal degrees to radians 
    lon1, lat1, lon2, lat2 = map(radians, [lon1, lat1, lon2, lat2])

    # haversine formula 
    dlon = lon2 - lon1 
    dlat = lat2 - lat1 
    a = sin(dlat/2)**2 + cos(lat1) * cos(lat2) * sin(dlon/2)**2
    c = 2 * asin(sqrt(a)) 
    r = 6378.137
    return c * r

lat, lon = map(float, raw_input().split(","))
r = float(raw_input())
raw_input()
d = {}
for line in sys.stdin:
    subscriber  = line.strip().split(",")

    dat = datetime.strptime(subscriber[0], "%m/%d/%Y %H:%M")
    h = haversine(lon, lat, float(subscriber[2]), float(subscriber[1]))
    if subscriber[3] in d:
        if dat > d[subscriber[3]][0]:
            d[subscriber[3]] = [dat, h]
    else:
        d[subscriber[3]] = [dat, h]
res = []
for phone in d:
    if  d[phone][1]<=r:
        res.append(phone)

print ",".join([phone for phone in sorted(res)])