import java.util.Random; public class Heuristics { /******************** * Helper Functions * ********************/ /** * Generates a Pair array of random length (10-15) with random (x, y) values (0, 9) * * @return a random Pair array */ private static Pair[] generatePairArray() { Random rand = new Random(); int length = 10 + rand.nextInt(5); //array length (10-15) int x = rand.nextInt(10); int y = rand.nextInt(10); Pair[] arr = new Pair[length]; for(int i = 0; i < length; i++) { arr[i] = new Pair(x, y); x = rand.nextInt(10); y = rand.nextInt(10); } return arr; } /** * Calculates Euclidean distance between two (x, y) points * * @param a a Pair * @param b a Pair * @return the distance between a and b */ private static double calculateDistance(Pair a, Pair b) { int x1 = a.getX(); int x2 = b.getX(); int y1 = a.getY(); int y2 = b.getY(); double t = (double) x1 - x2; double s = (double) y1 - y2; double dist = Math.sqrt(Math.pow(t, 2) + (Math.pow(s, 2))); return dist; } /** * Loops through every element in an array, starting at index, and finds * element that is closest to Pair p * * @param p a Pair * @param index a non-negative integer * @param arr a Pair array * @return the index i such that arr[i] is closest element in arr to p */ private static int findShortestDistanceIndex(Pair p, int index, Pair[] arr) { double temp = Double.POSITIVE_INFINITY; int j = -1; for (int i = index; i < arr.length; i++) { double sqrt = calculateDistance(p, arr[i]); if (sqrt < temp) { temp = sqrt; j = i; } } return j; } /** * Swaps elements arr[i] and arr[j] * * @param arr a Pair array * @param i a non-negative integer * @param j a non-negative integer */ private static void swap(Pair[] arr, int i, int j) { Pair temp = arr[i]; arr[i] = arr[j]; arr[j] = temp; } /** * Sees if a given x and y exists in a Pair array. If found, returns a Pair containing the index * the Pair is located in arr, as well as the boolean TRUE. If not found, a Pair containing an * index of -1 and the boolean FALSE is returned. * * @param arr a Pair array * @param x an integer * @param y an integer * @return a Pair containing the index of the desired (x, y) Pair and a boolean */ private static Pair contains(Pair[] arr, int x, int y) { for(int i = 0; i < arr.length; i++) { if((arr[i].getX() == x) && (arr[i].getY() == y)) { return new Pair(i, true); } } return new Pair(-1, false); } /** * Searches through a Pair array and returns the Pair with the largest y-value * * @param arr a Pair array * @return the Pair in arr with the largest y-value */ private static Pair findMaxY(Pair[] arr) { int min = (int)Double.NEGATIVE_INFINITY; Pair ret = new Pair(min, min); for(int i = 0; i < arr.length; i++) { if(arr[i].getY() > ret.getY()) { ret.setX(arr[i].getX()); ret.setY(arr[i].getY()); } } return ret; } /** * Given a Pair array, calculates the distance between each of the elements * * @param arr a Pair array */ private static void calculateTotalDistance(Pair[] arr) { int totalDistance = 0; for (int i = 0; i < arr.length - 1; i++) { double dist = calculateDistance(arr[i], arr[i+1]); totalDistance += dist; } System.out.println("Total Distance: " + totalDistance); } /********************* * Homework Problems * *********************/ /** * Orders an array of Pairs by selecting a random element in arr, finding * the closest element in arr to that random element, then repeating, comparing consecutive * elements as it continues down arr * * @param arr a Pair array */ public static void closestPointNext(Pair[] arr) { if (arr.length > 2) { /* picks random element and moves to front of array */ Random rand = new Random(); int i = rand.nextInt(arr.length); swap(arr, 0, i); /* walks through each element of arr and determines which element is closest to it, * then places that at next index in arr */ for (int j = 0; j < arr.length - 1; j++) { int index = findShortestDistanceIndex(arr[j], j + 1, arr); if (index > -1) { swap(arr, j + 1, index); } } } } /** * Does a diagonal sweep from the top-left corner to the bottom-right corner, placing the elements * in arr in order as they are found along this search. If two elements are on the same diagonal, * the leftmost one is seen first * * @param arr a Pair array */ public static void sweepDiagonal(Pair[] arr) { int index = 0; int location = 0; //placeholder for where to swap matches in arr int round = 0; Pair p = findMaxY(arr); int max = p.getX() + p.getY(); //max y search is x + y from (x, y) pair found in findMaxY for(int y = 0; y < max; y++) { int x = 0; while (y > -1) { /* if arr contains (x, y), put it next in arr */ if (contains(arr, x, y).getZ()) { index = contains(arr, x, y).getX(); swap(arr, index, location); location++; } y--; x++; } /* keeps track of how many times y was decremented, so the next round of searching continues * on the next diagonal further out from the origin */ round++; y = round; } } /** * Randomly orders arr * * @param arr a Pair array */ public static void randomOrder(Pair[] arr) { if (arr.length > 2) { /* picks a random element in arr and puts that next in line */ Random rand = new Random(); for (int i = 0; i < arr.length; i++) { /* chooses an element that hasn't been selected yet */ int index = i + rand.nextInt(arr.length - i); swap(arr, i, index); } } } /** * Orders an array of Pairs by selecting a random element in arr, finding * the closest element in arr to that random element, then repeating, ordering * arr by elements that are progressively farther away from the original random element * * @param arr */ public static void closestToStartingPoint(Pair[] arr) { if (arr.length > 2) { /* picks random element of arr and moves to front of array */ Random rand = new Random(); int i = rand.nextInt(arr.length); swap(arr, 0, i); /* walks through each element of arr and determines which element is closest to * the starting point, arr[0] */ for (int j = 1; j < arr.length - 1; j++) { int index = findShortestDistanceIndex(arr[0], j, arr); if (index > -1) { swap(arr, j, index); } } } } public static void main(String[] args) { /* An array to hold 10 Pair arrays */ Pair[][] pairArr = {null, null, null, null, null, null, null, null, null, null}; /* Sets each element of pairArr to be a randomized Pair array */ for(int i = 0; i < pairArr.length; i++) { pairArr[i] = generatePairArray(); } /* Walks through every Pair array within pairArr and performs four heuristics while also * calculating total distance traveled between points for each heuristic */ for(int i = 0; i < pairArr.length; i++) { System.out.println("Original array:"); /* Prints out starting Pair array */ for (int j = 0; j < pairArr[i].length; j++) { System.out.print("(" + pairArr[i][j].getX() + ", " + pairArr[i][j].getY() + ")\n"); } System.out.println(); //added for clarity of console output /* Closest Point First*/ closestPointNext(pairArr[i]); System.out.print("Closest Point First "); calculateTotalDistance(pairArr[i]); /* Diagonal Sweep */ sweepDiagonal(pairArr[i]); System.out.print("Diagonal "); calculateTotalDistance(pairArr[i]); /* Random Order */ randomOrder(pairArr[i]); System.out.print("Random "); calculateTotalDistance(pairArr[i]); /* Personal Heuristic */ closestToStartingPoint(pairArr[i]); System.out.print("Personal "); calculateTotalDistance(pairArr[i]); System.out.println(); //added for clarity of console output } } }