import java.util.Scanner; import java.util.ArrayList; import java.io.File; import java.io.FileNotFoundException; /* Java application whose purpose is to test the methods in the ** SaddleBackSearcher class. The user is invited to specify the ** dimensions of a matrix (i.e., # of rows and # of columns) and a seed ** for a pseudorandom number generator. A matrix of those dimensions and ** suitable for searching via the Saddleback Search approach is created, ** containing integer values that are pseudorandomly generated. ** The user can then repeatedly ask for searches to be carried out. ** ** Author: R. McCloskey ** Date: April 2022 */ public class SB_Tester { private static final int DEFAULT_FIELD_WIDTH = 4; private static Scanner input; private static boolean echo; public static void main(String[] args) throws FileNotFoundException { // Establish the input source; either the keyboard or the file whose // name is the first command line argument. if (args.length == 0) { input = new Scanner(System.in); echo = false; } else { input = new Scanner(new File(args[0])); echo = true; } System.out.println("Welcome to the RecSaddleBackSearcher tester."); int[][] mat = makeMatrix(); System.out.println(); showMatrix(mat, DEFAULT_FIELD_WIDTH); performTests(mat); System.out.println("Goodbye from the RecSaddleBackSearcher tester."); } private static void performTests(int[][] matrix) { // Create a new Recursive SaddleBack Searcher with the given // resident matrix. RecSaddleBackSearcher rsbs = new RecSaddleBackSearcher(matrix); boolean keepGoing = true; while (keepGoing) { System.out.print("\nEnter a search key (or Q, or S): "); String response = input.nextLine().trim(); if (response.charAt(0) == 'Q') { keepGoing = false; } else if (response.charAt(0) == 'S') { System.out.println(); showMatrix(matrix, DEFAULT_FIELD_WIDTH); } else { Scanner glork = new Scanner(response); if (glork.hasNextInt()) { int key = glork.nextInt(); rsbs.findAll(key); reportResults(rsbs); rsbs.resetProbeCount(); } else { System.out.println("Invalid response."); } } } } /* Reports the results of the most recent search performed by the ** given RecSaddleBackSearcher object. If the list of locations ** it reports (as containing the search key) does not agree with the ** number of occurrences of */ private static void reportResults(RecSaddleBackSearcher rsbs) { ArrayList locs = rsbs.getLocs(); System.out.printf("The search for %d involved %d probes ", rsbs.getKey(), rsbs.probeCount()); System.out.printf("and yielded this list of locations:\n%s\n", locs); int numOccur = occurrenceCount(rsbs.residentMatrix(), rsbs.getKey()); if (locs.size() != numOccur) { System.out.printf("ERROR: # of locations found (%d)", locs.size()); System.out.printf(" not equal to actual # occurrences (%d)\n", numOccur); } // Display an error message for any location in locs that does not // contain the search key. verifyLocs(rsbs.residentMatrix(), rsbs.getKey(), locs); } /* For each location indicated in the given list, the value within that ** location of the given matrix is compared to the given key. If they ** are not equal, an error message is displayed. */ private static void verifyLocs(int[][] ary, int key, ArrayList list) { for (GridLocation gLoc : list) { if (ary[gLoc.ROW][gLoc.COL] != key) { System.out.printf("**ERROR: location %s contains %d, not %d\n", gLoc, ary[gLoc.ROW][gLoc.COL], key); } } } /* Returns the # of occurrences of the give value in the given two-dim ** array, using an exhaustive search. ** An improvement would be to perform a binary search in each row. */ private static int occurrenceCount(int[][] ary, int val) { int cntr = 0; for (int i = 0; i != ary.length; i++) { for (int j = 0; j != ary[i].length; j++) { if (ary[i][j] == val) { cntr++; } } } return cntr; } /* Returns a two-dim matrix in accord with choices made by input values. */ private static int[][] makeMatrix() { int numRows = getInt("Enter # rows in matrix: "); int numCols = getInt("Enter # columns in matrix: "); int seed = getInt("Enter seed for pseudorandom # generation: "); // Create a matrix with the specified # of rows and columns, containing // values bounded below by zero, and in which each element exceeds the // larger of its immediate predecessors by between 1 and 5. return TwoDimArrayMaker.make(numRows, numCols, 0, 1, 5, seed); } /* Prints the given prompt and returns the response, as read via ** the global Scanner. The response is assumed to be a String that ** is amenable to translation to an int by Integer.parseInt(). */ private static int getInt(String prompt) { System.out.print(prompt); int response = Integer.parseInt(input.nextLine().trim()); if (echo) { System.out.printf("%d\n", response); } return response; } /* Displays the given 2-dim array, placing each value in a field ** of the specified width. */ private static void showMatrix(int[][] ary, int width) { int numRows = ary.length; int numCols = ary[0].length; String format = "%" + width + "d"; // print the column headings System.out.print(" "); for (int j = 0; j != numCols; j++) { System.out.printf(format, j); } System.out.print("\n +"); printDashes(numCols * width); System.out.println(); for (int i=0; i != numRows; i++) { System.out.printf(format + "|", i); for (int j=0; j != ary[i].length; j++) { System.out.printf(format, ary[i][j]); } System.out.println(); } } private static void printDashes(int num) { for (int k=0; k != num; k++) { System.out.print('-'); } } }