/* Programmer: Sriram Pemmaraju. Oct 24th, 2007 */ import java.util.StringTokenizer; import java.util.Arrays; import java.io.*; public class City{ // Arrays to keep track of info. related to each city private String[] cityName; private String[] cityState; private int[] cityLat; private int[] cityLong; private int[] cityPop; // 2-D array to keep track of pairwise distances between cities private int[][] distances; // boolean 1-D array to keep track of selected cities private boolean[] currentCities; // boolean 2-D array to keep track of selected edges private boolean[][] currentEdges; // number of cities private static int numCities = 128; public City() { //Allotting the space for each 1-D array cityName = new String[numCities]; cityState = new String[numCities]; cityLat = new int[numCities]; cityLong = new int[numCities]; cityPop = new int[numCities]; currentCities = new boolean[numCities]; // Select all cities initially for(int i = 0; i < numCities; i++) currentCities[i] = true; // Allocate space for each 2-D array. These arrays have 0 elements in row 0, // 1 element in row 1, 2 elements in row 2, etc. distances = new int[numCities][]; currentEdges = new boolean[numCities][]; for(int i = 0; i < numCities; i++) { distances[i] = new int[i]; currentEdges[i] = new boolean[i]; // Select all edges initially for(int j = 0; j < i; j++) currentEdges[i][j] = true; } try{ // Construct a buffered reader object and connect it to the files "miles.dat" BufferedReader in = new BufferedReader(new FileReader("miles.dat")); // A counter that keeps track of the index of the current city being read int cityNumber = 0; // While-loop for reading in data from "miles.dat." At the beginning of the while-loop // the expectation is that we'll be reading a line containing the city name. Instead, // if we encounter a line that starts with "*" then we skip to the next line while(cityNumber < numCities) { // Read in a line String line = in.readLine(); // Skip the rest of the loop if line starts with a "*" if(line.charAt(0) == '*') continue; // Otherwise tokenize the line StringTokenizer tokenizedLine= new StringTokenizer(line, ",[]"); //Putting actual data into correct position in the array cityName[cityNumber] = tokenizedLine.nextToken(); cityState[cityNumber]= (tokenizedLine.nextToken()).trim(); // trim() gets rid of leading/trailing blanks cityLat[cityNumber] = Integer.parseInt(tokenizedLine.nextToken()); cityLong[cityNumber] = Integer.parseInt(tokenizedLine.nextToken()); cityPop[cityNumber] = Integer.parseInt(tokenizedLine.nextToken()); //while loop to put distances in the array; this may need to read several lines int mileNumber = 0; while (mileNumber < cityNumber) { // Read a mileage line and tokenize it String mileage = in.readLine(); StringTokenizer tokenizedMileage = new StringTokenizer(mileage, " "); // Read all the mileage data in this line into row cityNumber; increment // mileNumber after each read while(tokenizedMileage.hasMoreTokens()) { distances[cityNumber][cityNumber-mileNumber-1] = Integer.parseInt(tokenizedMileage.nextToken()); //distances[cityNumber][mileNumber] = Integer.parseInt(tokenizedMileage.nextToken()); mileNumber++; } } // end of while reading distances cityNumber++; } // end of while reading cities } // end of try catch (IOException e) {System.out.println("File not found.");} } // end of City() constructor // Constructs a String array of all distinct state names of selected cities String[] getStates() { String[] states = new String[numCities]; int count = 0; for(int i = 0; i < numCities; i++) states[count++] = cityState[i]; // Sort the states array Arrays.sort(states); // Get rid of duplicates and create a new String array with // only distinct states String[] distinctStates = new String[count]; int distinctCount = 0; String previousState = null; for(int i = 0; i < count; i++) if(!states[i].equals(previousState)) { distinctStates[distinctCount++] = states[i]; previousState = states[i]; } // Resize the distinctStates array so that it has exactly the right size String[] newDistinctStates = new String[distinctCount]; for(int i = 0; i < distinctCount; i++) newDistinctStates[i] = distinctStates[i]; return newDistinctStates; } // Selects all cities void selectAllCities() { for(int i = 0; i < numCities; i++) currentCities[i] = true; } // Unselects all cities void unselectAllCities() { for(int i = 0; i < numCities; i++) currentCities[i] = false; } // Select cities: This version of the method allows us to select cities by name or by state name // This method only selects from among those cities that have already been selected void selectCities(String attribute, String lowerBound, String upperBound) { if(attribute.equals("name")) { // Scan all cities and unselect those select cities whose latitude is out of bounds for(int i = 0; i < numCities; i++) if((currentCities[i])&&((cityName[i].compareTo(lowerBound) < 0) || (cityName[i].compareTo(upperBound) > 0))) currentCities[i] = false; } if(attribute.equals("state")) { // Scan all cities and unselect those select cities whose latitude is out of bounds for(int i = 0; i < numCities; i++) if((currentCities[i])&&((cityState[i].compareTo(lowerBound) < 0) || (cityState[i].compareTo(upperBound) > 0))) currentCities[i] = false; } } // Select cities: This version of the method allows us to select cities by latitude or longitude // This method only selects from among those cities that have already been selected void selectCities(String attribute, int lowerBound, int upperBound) { if(attribute.equals("latitude")) { // Scan all cities and unselect those select cities whose latitude is out of bounds for(int i = 0; i < numCities; i++) if((currentCities[i])&&((cityLat[i] < lowerBound) || (cityLat[i] > upperBound))) currentCities[i] = false; } if(attribute.equals("longitude")) { // Scan all cities and unselect those select cities whose latitude is out of bounds for(int i = 0; i < numCities; i++) if((currentCities[i])&&((cityLong[i] < lowerBound) || (cityLong[i] > upperBound))) currentCities[i] = false; } if(attribute.equals("population")) { // Scan all cities and unselect those select cities whose latitude is out of bounds for(int i = 0; i < numCities; i++) if((currentCities[i])&&((cityPop[i] < lowerBound) || (cityPop[i] > upperBound))) currentCities[i] = false; } } // Selects edges whose distance lies in-between the specified lower and upper bounds, // inclusive of the bounds. This function pays no attention to past edge selections void selectEdges(int lowerBound, int upperBound) { for(int i = 0; i < numCities; i++) for(int j = 0; j < i; j++) if((distances[i][j] >= lowerBound) && (distances[i][j] <= upperBound)) currentEdges[i][j] = true; else currentEdges[i][j] = false; } // Constructs and returns a graph whose vertices are the set of selected cities and whose // edges are selected edges that connected pairs of selected cities myListGraph makeGraph() { // Create an empty graph myListGraph g = new myListGraph(); // Add all selected cities to it for(int i = 0; i < numCities; i++) if(currentCities[i]) g.addVertex(cityName[i]+" "+cityState[i]); // Add all selected edges between pairs of selected cities for(int i = 0; i < numCities; i++) for(int j = 0; j < i; j++) if((currentEdges[i][j]) && (currentCities[i]) && (currentCities[j])) g.addEdge(cityName[i]+" "+cityState[i], cityName[j]+" "+cityState[j]); // return the constructed graph return g; } // Prints the selected cities void printCities() { // Scan the list of all cities and print out those that are selected for(int i = 0; i < numCities; i++) if(currentCities[i]) System.out.println(cityName[i]+" "+cityState[i]); } // Gets the populations of selected cities in an int array int[] getPopulations() { // First count the number of selected cities int count = 0; for(int i = 0; i < numCities; i++) if(currentCities[i]) count++; // Use this count to define an array of the correct size to hold the // populations int[] popArray = new int[count]; // Fill this array with the populations of the selected cities count = 0; for(int i = 0; i < numCities; i++) if(currentCities[i]) popArray[count++] = cityPop[i]; return popArray; } // A simple getIndex method to help test the constructor int getIndex(String city, String state) { int location; for(location = 0; location < numCities; location++) if((cityName[location].equals(city)) && (cityState[location].equals(state))) return location; return -1; } // Print information about a city, given a city index void printCityInfo(int index) { System.out.println(cityName[index] + " " + cityState[index] + " " + cityLat[index] + " " + cityLong[index] + " " + cityPop[index]); } // Print distance information between a given pair of cities void printDistanceInfo(int i, int j) { if(i < j) System.out.println(distances[j][i]); else System.out.println(distances[i][j]); } //Main method public static void main(String[] args) { City newCity = new City(); myListGraph g; String[] path; System.out.println("---------------------------------------------------------------------------------------"); System.out.println("EXPERIMENT 1"); // Select edges in the range 0 through 200 miles and make a graph int upperBound = 200; while(true) { newCity.selectEdges(0, upperBound); g = newCity.makeGraph(); System.out.println("Constructed a graph with all cities and edges only at most " + upperBound + " miles long."); System.out.println("Vertices = " + g.numberOfVertices() + " " + "Edges = " + g.numberOfEdges()); // Compute shortest path between Yakima, WA and Wilmington, DE path = g.shortestPath("Yakima WA", "Wilmington DE"); if(path == null) System.out.println("There is no path from Yakima, WA to Wilmington, DE"); else { System.out.println("The shortest path from Yakima, WA to Wilmington, DE is"); for(int i = 0; i < path.length; i++) System.out.print(path[i]+" "); System.out.println(" "); break; } upperBound = upperBound + 50; } System.out.println("---------------------------------------------------------------------------------------"); System.out.println("EXPERIMENT 2"); // Select cities in the upper midwest newCity.selectCities("latitude", 4000, 5000); newCity.selectCities("longitude", 8500, 10000); // Print these out System.out.println("Cities in the upper mid-west are:"); newCity.printCities(); int[] popArray = newCity.getPopulations(); int max = 0; for(int i = 0; i < popArray.length; i++) if(popArray[i]/20000 > max) max = popArray[i]/20000; int[] popDist = new int[max+1]; for(int i = 0; i < popArray.length; i++) popDist[popArray[i]/20000]++; System.out.println("The population distribution of these cities is:"); for(int i = 0; i < popDist.length; i++) System.out.println("["+(20000*i)+","+(20000*(i+1))+"] "+popDist[i]); System.out.println("---------------------------------------------------------------------------------------"); System.out.println("EXPERIMENT 3"); newCity.selectAllCities(); String[] states = newCity.getStates(); System.out.println("Here are all the states:"); for(int i = 0; i < states.length; i++) System.out.print(states[i]+" "); System.out.println(" "); // Scan through the states and select all the cities in that state System.out.println("Here are their populations:"); long maxPopulation = 0; String maxPopState = null; for(int i = 0; i < states.length; i++) { newCity.selectAllCities(); newCity.selectCities("state", states[i], states[i]); popArray = newCity.getPopulations(); long popSum = 0; for(int j = 0; j < popArray.length; j++) popSum = popSum + popArray[j]; System.out.println(states[i] + " " + popSum); if(popSum > maxPopulation) { maxPopulation = popSum; maxPopState = states[i]; } } System.out.println("The most populous state is " + maxPopState + " with a population of " + maxPopulation); } }