import java.util.Arrays; import java.util.Scanner; import java.io.File; import java.io.FileNotFoundException; /* Java application that includes a method that computes the maximum ** among the lengths of the plateaus in a given array. ** The remaining methods are for the purpose of testing that method. ** ** Author: R. McCloskey and < STUDENT's NAMES(s) > ** Known Defects: */ public class MaxLenPlateauApp { /* This method expects a single run (i.e., command line) argument that ** names a data file. That file is expected to contain test data by ** which to construct arrays to be fed to the lengthOfLongestPlateau() ** method. Each line of the file is expected to contain a sequence of ** integer numerals that is used to populate an array. Each such array ** is passed to the method to determine the maximum among the lengths ** of its plateaus. ** */ public static void main(String[] args) throws FileNotFoundException { Scanner input = new Scanner(new File(args[0])); while (input.hasNextLine()) { int[] ary = readArray(input); System.out.println("Array:"); System.out.println(Arrays.toString(ary)); System.out.println("Computing length of longest plateau ..."); int len = lengthOfLongestPlateau(ary); System.out.println("Longest plateau is of length " + len); System.out.println(); } System.out.println("Goodbye"); } /* Returns the maximum among the lengths of the plateaus in the given array. ** Here we define "plateau" to mean any array segment all of whose elements ** have the same value. That is, a[low .. high) is a plateau (of length ** high-low) if a[low] == a[low+1] == ... == a[high-1]. This plateau is ** said to be "left-maximal" if either low == 0 or a[low-1] != a[low]. ** Similarly, it is a right-maximal plateau if either high == a.length or ** a[high-1] != a[high]. Obviously, a plateau of maximum length must be ** both left- and right-maximal. ** pre: a.length != 0 */ public static int lengthOfLongestPlateau(int[] a) { int maxLenSoFar = ?; int leftEnd = ?; int k = ?; // loop invariant: // 1 <= k <= a.length && // maxLenSoFar == length of longest plateau in a[0..k) && // a[leftEnd .. k) is a left-maximal plateau assert loopInvariant(a, leftEnd, k, maxLenSoFar); while ( ?? ) { // MISSING loop body assert loopInvariant(a, leftEnd, k, maxLenSoFar); } // postcondition: maxLenSoFar == length of longest plateau // in a[0..k) and k == a.length return maxLenSoFar; } /* Returns the true/false value of the loop invariant of the ** method above. */ private static boolean loopInvariant(int[] a, int leftEnd, int k, int maxLenSoFar) { boolean goodSoFar = true; if (!(1 <= k && k <= a.length)) { goodSoFar = false; System.out.printf("WARNING: %d out of range [%d..%d)\n\n", k, 1, a.length); } if (!isLeftMaximalPlateau(a, leftEnd, k)) { goodSoFar = false; System.out.printf("WARNING: a[%d..%d) is not a left-maximal plateau\n\n", leftEnd, k); } if (!isMaxAmongPlateauLengths(a,k, maxLenSoFar)) { goodSoFar = false; System.out.printf("%d != length of longest plateau in a[0..%d)\n\n", maxLenSoFar, k); } return goodSoFar; } /* Reports whether or not b[low..high) is a left-maximal plateau, ** meaning that it is a plateau but b[low-1..high) is not, either ** because low == 0 or b[low-1] != b[low]. ** pre: 0 <= low < high <= b.length */ private static boolean isLeftMaximalPlateau(int[] b, int low, int high) { return (low == 0 || b[low-1] != b[low]) && isPlateau(b, low, high); } /* Reports whether or not b[low..high) is a plateau. ** pre: 0 <= low < high <= b.length */ private static boolean isPlateau(int[] b, int low, int high) { boolean goodSoFar = true; int i = low + 1; while (goodSoFar && i != high) { if (b[i-1] != b[i]) { goodSoFar = false; } i = i+1; } return goodSoFar; } /* Reports whether or not len is the maximum among the lengths of ** the plateaus in b[0..high). */ private static boolean isMaxAmongPlateauLengths(int[] b, int high, int len) { boolean foundLenK = false; boolean foundLenK_plusOne = false; int i = 0; while (i+len <= high && !foundLenK_plusOne) { if (isLeftMaximalPlateau(b, i, i+len)) { // b[i..i+len) is a left-maximal plateau within b[0..high), // but is it also right-maximal? If not, a plateau of length // len+1 exists. foundLenK = true; if (i+len < high && b[i+len-1] == b[i+len]) { foundLenK_plusOne = true; } } i = i+1; } return foundLenK && !foundLenK_plusOne; } /* Reads a line from the source to which the given Scanner is bound, ** under the assumption that the tokens on that line (separated by ** whitespace) are integer numerals. An array containing the ** corresponding numbers is returned. */ private static int[] readArray(Scanner input) { // Read a line of input. String line = input.nextLine(); // Place the tokens on that line into an array of Strings String[] items = line.split("\\s+"); // Convert the Strings into int's and place them into an array int[] result = new int[items.length]; for (int i=0; i != items.length; i++) { result[i] = Integer.parseInt(items[i]); } return result; // Return the resultant array. } }