# Autho : Steven Miller # Course : 22C:016 SCA # ID : 478465327 ''' Phase 1 of Programming Project 1 ''' import string def storeCity(line,cities) : ''' Extracts the city name and state and stores it. ''' city = line[:line.index(',')].strip() state = line[line.index(',')+1:line.index('[')].strip() cities.append(city + ' ' + state) def storePopulation(line,population) : ''' Extracts the population from a line and stores it. ''' population.append(int(line[line.index(']')+1:])) def storeCoordinates(line,coordinates) : ''' Extracts the coordinates from a line and stores them. ''' coordinates.append(map(int, line[line.index('[')+1 : line.index(']')].split(','))) def storeDistances(newDistances,distances) : ''' Stores the distances to/from each city to the current city. ''' # Skip over the first city since its distances haven't been seen yet if not cities : return # Convert all new distances to integers newDistances = map(int, newDistances) # Compute dimension of new distances array - 1 n = len(newDistances)-1 # Set the distance of city from itself to zero distances.append([0]) # For each city already seen for i in range(n+1) : # Append the distance to this city distances[n-i] = distances[n-i] + [newDistances[i]] # Insert the distance from this city distances[n+1] = [newDistances[i]] + distances[n+1] def isCityLine(line) : ''' Returns whether a line contains city information.''' return line[0].isalpha() def isDistanceLine(line) : ''' Returns whether a line contains distance information.''' return line[0].isdigit() def readCitiesData(filename) : """ Reads the city's data and populates the data structures """ accDist = [] # Accumulates distances seen over several lines f = open(filename, "r") for line in f: # If this line has distances, accumulate the new distances if isDistanceLine(line) : accDist = accDist + line.split() # If this line has data for a new city elif isCityLine(line) : # Store the distances accumulated for the previous city storeDistances(accDist,distances) accDist = [] # Store the name, coordinates, and popuation for this city storeCity(line,cities) storeCoordinates(line,coordinates) storePopulation(line,population) f.close() # Store the distances for the last city storeDistances(accDist,distances) def getCoordinates(name) : ''' Returns the coordinates for a city as a list of lat and long. Returns an empty list if the city name is invalid. ''' result = [] if name in cities : result = coordinates[cities.index(name)] return result def getPopulation(name) : ''' Returns the popultion for a city. Returns None if the city name is invalid.''' result = None if name in cities : result = population[cities.index(name)] return result def getDistance(name1, name2) : ''' Returns the distance between two cities. Returns None if either city's name is invalid.''' result = None if name1 in cities and name2 in cities : result = distances[cities.index(name1)][cities.index(name2)] return result def nearbyCities(name, r) : ''' Returns a list of cities within distance r of named city sorted in alphabetical order. Returns an empty list if city name is invalid. ''' result = [] if name in cities : # If the city name is valid i = cities.index(name) # Get the index of the named city for j in range(len(cities)) : # For every other city if distances[i][j] <= r : # If within r of named city result = result + [cities[j]] # Add to result result.sort() return result def unserved(served, cities, city, r) : ''' Returns the number of unserved cities within distance r of city. ''' result = 0 # for each city within distance r of city for c in nearbyCities(city, r) : # if not served, add it to the list of unserved citys if not served[cities.index(c)] : result = result + 1 return result def nextFacility(served, cities, distances, r) : ''' Returns the name of the city that can service the most unserved cities within radius r. Returns None if all cities are served. ''' facility = None # Name of city that will be the next service facility numberServed = 0 # Number of cities that facility will serve # For each city for c in range(len(cities)) : # compute how many unserved cities will be served by city c if not served[c]: willBeServed = unserved(served, cities, cities[c], r) # if it can serve more cities than the previous best city if willBeServed > numberServed: # make it the service center facility = cities[c] numberServed = willBeServed return facility def locateFacilities(cities, distances, r) : ''' Returns an alphabetically sorted list of the cities in which facilities must be located to service all cities with a service radius of r. ''' # List of cities that are served by current facilities served = [False] * len(cities) # List of cities that are service facilities facilities = [] # Get the city that is the next best service facility facility = nextFacility(served, cities, distances, r ) # While there are more cities to be served while facility : # Mark the service facility as served served[cities.index(facility)] = True # Mark each city as served that will be served by this facility for city in nearbyCities(facility, r) : served[cities.index(city)] = True # Append the city to the list of service facilities facilities.append(facility) # Get the city that is the next best service facility facility = nextFacility(served, cities, distances, r) # Sort the list of facilties alphabetically facilities.sort() return facilities """ Main body of the program. """ cities = [] # List of valid city names (city name and state) coordinates = [] # Coordinates (lat and long) of each city population = [] # Population of each city distances = [] # Distances to/from each pair of cities # Read the map data for each city and store in data structures readCitiesData("miles.dat")