Question
Part 2: ZIP code look up and distance calculation As part of an Open Data Policy, the U.S. Government released a large number of datasets
Part 2: ZIP code look up and distance calculation
As part of an Open Data Policy, the U.S. Government released a large number of datasets to
conduct research, develop web and mobile applications, design data visualizations [1]. Among these
is a dataset that provides geographic coordinates for U.S. 5 digit ZIP codes. For this assignment,
we will be using a slightly improved version of the ZIP dataset available at [2]. For each ZIP code,
this dataset lists geographic coordinates (latitude and longitude), city, state, and county. Our goal
is to use available data to develop a new data product that would allow users not only to query
and search the existing data source but also to access additional functionality such as computing
the distance between two locations.
Write a program that would allow users to lookup locations by ZIP code, lookup ZIP codes by city
and state, and determine the distance between two locations designated by their ZIP codes. The
program interacts with the user by printing a prompt and allowing them to enter commands until
they enter 'end' at which point the program prints Done and finishes. If an invalid command is
entered, the program prints Invalid command, ignoring and is ready to take the next command.
The following commands are recognized:
1. loc allows the user to enter a ZIP code, then looks up city, state, county, and geographic
coordinates that correspond to the ZIP code and prints this data; If a ZIP code is invalid or
not found in the dataset, the program prints a error message instead. Look at the following
sample output:
Command ('loc', 'zip', 'dist', 'end') => loc
loc
Enter a ZIP code to lookup => 12180
12180
ZIP code 12180 is in Troy, NY, Rensselaer county,
coordinates: (04240'25.32"N,07336'31.65"W)
Note that coordinates are enclosed in parentheses and are separated by a comma; each coordinate
is printed in integer degrees (three digits), followed by the
symbol, integer minutes
(two digits), followed by the ' character, integer and fractional seconds (two integer and two
decimal digits), followed by the " character, and a cardinal direction letter (N, S, W, or E)
with no spaces anywhere in the coordinate representation.
2. zip allows the user to enter city and state, then looks up the ZIP code or codes (some cities
have more than one) which correspond to this location and prints them; if city and/or state
are invalid or not found in the dataset, it prints an error message instead.
Command ('loc', 'zip', 'dist', 'end') => zip
zip
Enter a city name to lookup => troY
troY
Enter the state name to lookup => ny
ny
The following ZIP code(s) found for Troy, NY: 12179, 12180, 12181, 12182, 12183
3. dist allows the user to enter two ZIP codes and computes the geodesic distance between the
location coordinates ; if any of the ZIP codes entered is invalid or not found in the dataset,
it prints a corresponding error message instead.
Command ('loc', 'zip', 'dist', 'end') => dist
dist
Enter the first ZIP code => 19465
19465
Enter the second ZIP code => 12180
12180
The distance between 19465 and 12180 is 201.88 miles
4. end stops fetching new commands from the user and ends the program
The utility module provided for this part of homework will give you some help. It provides a
function read_zip_all() that returns a list each element of which is, in turn, a list that contains
data about one zip code. Try the following:
import hw4_util
zip_codes = hw4_util.read_zip_all()
print(zip_codes[0])
print(zip_codes[4108])
would give:
['00501', 40.922326, -72.637078, 'Holtsville', 'NY', 'Suffolk']
['12180', 42.673701, -73.608792, 'Troy', 'NY', 'Rensselaer']
Note that the data on a particular ZIP code has the following fields in order: zip code (string),
latitude (float degrees), longitude (float degrees), city (string), state (string), and county (strings).
Implementation Details
You will need to define two functions that should strictly follow specifications outlined below:
1. zip_by_location(zip_codes, location) which finds the ZIP code for a given location.
Parameters:
zip_codes a list of ZIP codes data in the format, returned by read_zip_all()
location a two-element tuple where the first element is the city name and the second element
is the state abbreviation, e.g. ('trOy', 'nY'). Both elements are string values. City names
and state abbreviations can be written using any case or a mixture of lower and upper case.
Return value:
A list which contains ZIP code or codes for the specified location. Each ZIP code is a string
value. If the location is invalid, an empty list is returned.
E.g., ['12179', '12180', '12181', '12182', '12183']
2. location_by_zip(zip_codes, code) which finds location information corresponding to the
specified ZIP code.
Parameters:
zip_codes a list of ZIP codes and associated data in the format, returned by read_zip_all()
code ZIP code as a string value, e.g. '12180'.
Return value:
A five-element tuple ()latitude, longitude, city, state, county). Latitude and longitude
are in fractional degrees (floating point values). All other elements are string values.
E.g., (42.673701, -73.608792, 'Troy', 'NY', 'Rensselaer')
It is required that you implement functions according to specifications given above. You are also
expected to define other functions, as necessary. You need to determine which functions to define
and to design their specifications yourself, following the example we gave above for the two required
functions. Do not forget to include function specifications as comments right above the functions
definition in your code. Avoid copying and pasting repeated pieces of code. Those should be
factored out as functions. You may lose points for excessive duplication of code.
Hints and Helps
Formatting your output is a big part of this program. Here are a few hints.
1. The
symbol can be generated using another escape character similar to ' or '\t'. To
generate the
, use \xb0. Just like the tab and the newline, this is a single character.
2. When printing out the location, there is a tab character at the start of the second line before
coordinates.
3. if you want to print leading 0s before an integer, use the {:0Nd} where N is the total number
of spaces you want the integer to occupy. So a format of :07d will use 7 spaces to print your
integer, padding the front of the integer with 0s. I.e.
print("{:07d}".format(7))
will give
0000007
4. You will need to manage the latitude and longitude to convert among representations. In
particular, you need to convert the fractional degrees in the zip code list to degrees, minutes,
seconds. There are 60 minutes in a degree and 60 seconds in a minute. When you convert,
all of your latitudes and longitudes should be positive. Instead, use east (E) and west (W)
designators of longitude; and north (N) and south (S) designators for latitude. Negative
longitudes are west, positive are east. Negative latitudes are south, positives are north. In
bath cases, a latitude or longitude of 0 (the equator or the prime meridian, respectively) do
not have a designator.
5. The distance between two points on the surface of Earth uses a simplified haversine formula
for arc length on a sphere. You should implement Eq. 1 which assumes the Earth to be
spherical. This formula gives the shortest surface distance d as-the-crow-flies, ignoring
Earths relief.
latitude = latitude2 latitude1
longitude = longitude2 longitude1
a = sin2
latitude
2
+ cos(latitude1) cos(latitude2) sin2
longitude
2
d = 2R arcsin
a
(1)
Where R = 3959.191 miles is the radius of the Earth and all angle measurements are in
radians (the zip code data gives latitude and longitude in degrees).
Sample Output
Below is an example output that demonstrates program features:
Command ('loc', 'zip', 'dist', 'end') => loc
loc
Enter a ZIP code to lookup => 12180
12180
ZIP code 12180 is in Troy, NY, Rensselaer county,
coordinates: (04240'25.32"N,07336'31.65"W)
Command ('loc', 'zip', 'dist', 'end') => loc
loc
Enter a ZIP code to lookup => 1946
1946
Invalid or unknown ZIP code
Command ('loc', 'zip', 'dist', 'end') => loc
loc
Enter a ZIP code to lookup => 19465
19465
ZIP code 19465 is in Pottstown, PA, Chester county,
coordinates: (04011'30.87"N,07539'55.12"W)
Command ('loc', 'zip', 'dist', 'end') => loc
loc
Enter a ZIP code to lookup => 00000
00000
Invalid or unknown ZIP code
Command ('loc', 'zip', 'dist', 'end') => loc
loc
Enter a ZIP code to lookup => ksahdkja
ksahdkja
Invalid or unknown ZIP code
Command ('loc', 'zip', 'dist', 'end') => dist
dist
Enter the first ZIP code => 19465
19465
Enter the second ZIP code => 12180
12180
The distance between 19465 and 12180 is 201.88 miles
Command ('loc', 'zip', 'dist', 'end') => dist
dist
Enter the first ZIP code => 12180
12180
Enter the second ZIP code => 12180
12180
The distance between 12180 and 12180 is 0.00 miles
Command ('loc', 'zip', 'dist', 'end') => dist
dist
Enter the first ZIP code => 12180
12180
Enter the second ZIP code => 55499
55499
The distance between 12180 and 55499 cannot be determined
Command ('loc', 'zip', 'dist', 'end') => zip
zip
Enter a city name to lookup => troY
troY
Enter the state name to lookup => ny
ny
The following ZIP code(s) found for Troy, NY: 12179, 12180, 12181, 12182, 12183
Command ('loc', 'zip', 'dist', 'end') => zip
zip
Enter a city name to lookup => Amsterdam
Amsterdam
Enter the state name to lookup => NL
NL
No ZIP code found for Amsterdam, NL
Command ('loc', 'zip', 'dist', 'end') => help
help
Invalid command, ignoring
Command ('loc', 'zip', 'dist', 'end') => END
END
Done
When you have tested your code, please submit it as hw4Part2.py. Be sure to use the correct
filename or Submitty will not be able to grade your submission.
References
[1] Data.gov: The home of the U.S. Governments open data, 2018, Accessed on: Feb. 23, 2018.
[Online]. Available: https://www.data.gov/
[2] Download: Zip code latitude longitude city state county csv, San Diego, CA, USA,
2018, Accessed on: Feb. 23, 2018. [Online]. Available: https://www.gaslampmedia.com/
download-zip-code-latitude-longitude-city-state-county-csv/
Utility:
This is a utility module for Homework#4 in CSCI 1100 Fall 2015
For part 2, use the read_zip_all function to read the pokemon appearance information as follows:
zip_codes = hw4_util.read_zip_all() print(zip_codes[4108])
""" def read_zip_all(): i = 0 header = [] zip_codes = [] zip_data = [] skip_line = False # http://notebook.gaslampmedia.com/wp-content/uploads/2013/08/zip_codes_states.csv for line in open('zip_codes_states.csv').read().split(" "): skip_line = False m = line.strip().replace('"', '').split(",") i += 1 if i == 1: for val in m: header.append(val) else: zip_data = [] for idx in range(0,len(m)): if m[idx] == '': skip_line = True break if header[idx] == "latitude" or header[idx] == "longitude": val = float(m[idx]) else: val = m[idx] zip_data.append(val) if not skip_line: zip_codes.append(zip_data) return zip_codes
if __name__ == "__main__":
zip_codes = read_zip_all() print(zip_codes[4108])
Step by Step Solution
There are 3 Steps involved in it
Step: 1
Get Instant Access to Expert-Tailored Solutions
See step-by-step solutions with expert insights and AI powered tools for academic success
Step: 2
Step: 3
Ace Your Homework with AI
Get the answers you need in no time with our AI-driven, step-by-step assistance
Get Started