import java.util.Scanner; import java.util.Random; import java.io.File; import java.io.FileNotFoundException; /* Java application whose purpose is to test the Java class RWB_Partitioner, ** instances of which partition arrays containing values 'R', 'W', and 'B' ** (representing RED, WHITE, and BLUE, respectively) so that all the R's come ** first, followed by the W's, followed by the B's. ** The user is prompted to enter, for each color, how many elements of that ** color are to be placed into the array to be partitioned. The values are ** placed into the array in pseudo-random order, a clone is made of the ** array, and then RWB_Partitioner's partition() and partition2() methods are ** applied to the array and its clone, respectively. The results of ** partitioning are displayed. ** Note that the user is prompted to enter a seed to be used in creating ** the Random object; the seed value determines the order in which the array ** elements occur. Thus, by choosing the same seed on different runs of ** the program, the same array will be partitioned each time. */ public class RWB_PartTester { private static Scanner keyboard; private static boolean echo; public static void main(String[] args) throws FileNotFoundException { String promptSuffix = " to put in the array: "; String redPrompt = "Enter # of RED elements"; String whitePrompt = "Enter # of WHITE elements:"; String bluePrompt = "Enter # of BLUE elements:"; String randPrompt = "Enter (int) seed for pseudo-random # generation: "; System.out.println("Welcome to the partitioner tester program!"); // If a command line argument is provided, interpret it to be the // name of a file containing input data. if (args.length > 0) { File file = new File(args[0]); keyboard = new Scanner(file); echo = true; } else { keyboard = new Scanner(System.in); echo = false; } int numRed = getInt(redPrompt + promptSuffix); int numWhite = getInt(whitePrompt + promptSuffix); int numBlue = getInt(bluePrompt + promptSuffix); int randSeed = getInt(randPrompt); Random rand = new Random(randSeed); char[] a = randomArray(rand, numRed, numWhite, numBlue); System.out.println("Array to be partitioned:"); displayArraySegment(a, 0, a.length); System.out.println(); // Make a clone of a[] so that the partition() and partition2() // methods can be applied to identical arrays. char[] aClone = a.clone(); // Create an RWB_Partitioner object p RWB_Partitioner p = new RWB_Partitioner(); try { // Use p to partition a[] and then report the results. p.partition(a); System.out.println("\nAfter calling partition(), we have:"); reportResults(p); } catch (Throwable e) { e.printStackTrace(System.out); } try { // Now use p to partition aClone[] and then report the results. p.partition2(aClone); System.out.println("\nAfter calling partition2(), we have:"); reportResults(p); } catch (Throwable e) { e.printStackTrace(System.out); } } /* Displays the results of most recent partitioning. */ private static void reportResults(RWB_Partitioner part) { char[] ary = part.array(); System.out.print("Partitioned array: "); displayArraySegment(ary, 0, ary.length); System.out.println(); int rwBoundary = part.whiteStart(); int wbBoundary = part.blueStart(); System.out.printf("RED segment [%d,%d): ", 0, rwBoundary); displayArraySegment(ary, 0, rwBoundary); System.out.println(); System.out.printf("WHITE segment [%d,%d): ", rwBoundary, wbBoundary); displayArraySegment(ary, rwBoundary, wbBoundary); System.out.println(); System.out.printf("BLUE segment [%d,%d): ", wbBoundary, ary.length); displayArraySegment(ary, wbBoundary, ary.length); System.out.println(); System.out.println("# comparisons: " + part.numComparisons()); System.out.println("# swaps: " + part.numSwaps()); } /* Prints the specified string and returns the response entered at the ** keyboard, interpreted as an integer. */ private static int getInt(String prompt) { System.out.print(prompt); int result = keyboard.nextInt(); if (echo) { System.out.println(result); } return result; } /* Prints the values in the specified array segment (i.e., z[low..high)). */ private static void displayArraySegment(char[] z, int low, int high) { for (int i = low; i != high; i++) { System.out.print(z[i]); } } /* Returns a new array of type char[] containing the specified number ** of 'R', 'W', and 'B' values, put into pseudo-random order using the ** given Random object. */ private static char[] randomArray(Random r, int redCount, int whiteCount, int blueCount) { int N = redCount + whiteCount + blueCount; char[] result = new char[N]; fill(result, 0, redCount, 'R'); fill(result, redCount, redCount+whiteCount, 'W'); fill(result, redCount+whiteCount, N, 'B'); permute(result, r); return result; } /* Places the specified value into each element of the specified ** array segment (i.e., a[low..high)). */ private static void fill(char[] a, int low, int high, char value) { for (int i = low; i < high; i++) { a[i] = value; } } /* Permutes the elements of the given array pseudo-randomly, using ** the given Random object. */ private static void permute(char[] a, Random rand) { for (int i = a.length; i > 1; i--) { // Swap the value at location i-1 with that at some location // in the range [0..i). int randLocation = rand.nextInt(i); swap(a, i-1, randLocation); } } /* Swaps the elements at the specified locations of the specified array. */ private static void swap(char[] a, int j, int k) { char temp = a[j]; a[j] = a[k]; a[k] = temp; } }