import java.util.Random; import java.util.Scanner; import java.io.File; import java.io.FileNotFoundException; /* SOP_Tester.java ** Intended to be used by students for testing their SetOfPerson class. ** Author: R. McCloskey, November 2025 */ public class SOP_Tester { private static final String QUIT = "Q"; private static final String ADD = "A"; private static final String REMOVE = "R"; private static final String OTHERS = "T"; private static Scanner input; private static boolean echo; private static boolean keepGoing; private static Person[] people; public static void main(String[] args) { System.out.println("Welcome to the SetOfPerson Tester Program."); establishScanner(args); makePeople(); keepGoing = true; do { performTest(); } while (keepGoing); System.out.println("Goodbye."); } public static void performTest() { printMenu(); String response = getString("\n> ").toUpperCase(); if (response.equals(QUIT)) { keepGoing = false; } else if (response.equals(ADD)) { testAddPerson(); } else if (response.equals(REMOVE)) { testRemovePerson(); } else if (response.equals(OTHERS)) { testOthers(); } else { System.out.println("Invalid response; try again."); } } private static void testAddPerson() { SetOfPerson s = randomPersonSet(0, people.length, 8, (int)(10*Math.random())); s.resetWorkMeasure(); System.out.println("Start with this set:"); printSet(s); String name; String prompt = "\nEnter name of person to add (empty string to quit): "; do { name = getString(prompt); if (name.length() != 0) { Person p = new Person(name); boolean result = s.addPerson(p); System.out.println("\naddPerson() returned " + result + "; set is now:"); printSet(s); System.out.println("Work reported: " + s.workMeasure()); s.resetWorkMeasure(); } } while (name.length() != 0); } private static void testRemovePerson() { String prompt = "\nEnter name of person to remove (empty string to quit): "; SetOfPerson s = randomPersonSet(0, people.length, 8, (int)(10*Math.random())); s.resetWorkMeasure(); System.out.println("Start with this set:"); s.printNames(); String name; do { name = getString(prompt); if (name.length() != 0) { boolean result = s.removePerson(name); System.out.println("\nremovePerson() returned " + result + "; set is now:"); printSet(s); System.out.println("Work reported: " + s.workMeasure()); s.resetWorkMeasure(); } } while (name.length() != 0); } /* Prompts the user to "make" two sets (using elements of the people[] array) ** and then verifies that several relationships hold between them and their ** union, intersection, and difference. */ private static void testOthers() { SetOfPerson A = userMadeSet(); System.out.println("Set A is"); printSet(A); System.out.println(); SetOfPerson B = userMadeSet(); System.out.println("\nSet B is"); printSet(B); A.resetWorkMeasure(); B.resetWorkMeasure(); SetOfPerson A_union_B = A.unionWith(B); System.out.println("\nunionWith() says A union B is"); printSet(A_union_B); SetOfPerson A_intersect_B = A.intersectionWith(B); System.out.println("\nintersectionWith() says A intersect B is"); printSet(A_intersect_B); SetOfPerson A_minus_B = A.difference(B); System.out.println("\ndifference() says A minus B is"); printSet(A_minus_B); // Verify that the sum of the sizes of A and B is equal to // the sum of the sizes of A_union_B and A_intersect_B int size_A_union_B = A_union_B.sizeOf(); int size_A_intersect_B = A_intersect_B.sizeOf(); if (A.sizeOf() + B.sizeOf() != size_A_union_B + size_A_intersect_B) { System.out.println("ERROR: |A| + |B| != |AuB| + |A^B|"); } // Verify that the size of A-B is same as size of A minus size of A^B int size_A_minus_B = A_minus_B.sizeOf(); if (size_A_minus_B != A.sizeOf() - size_A_intersect_B) { System.out.println("ERROR: |A-B| != |A| - |A^B|"); } // Verify that both A and B are subsets of A_union_B if (!A.isSubsetOf(A_union_B)) { System.out.println("ERROR: isSubsetOf() reports that A is not a subset of AuB"); } if (!B.isSubsetOf(A_union_B)) { System.out.println("ERROR: isSubsetOf() reports that B is not a subset of AuB"); } if (A_union_B.isSubsetOf(A)) { System.out.println("WARNING: isSubsetOf() reports AuB is a subset of A"); } if (A_union_B.isSubsetOf(B)) { System.out.println("WARNING: isSubsetOf() reports AuB is a subset of B"); } // Verify that A_intersect_B is a subset of both A and B if (!A_intersect_B.isSubsetOf(A)) { System.out.println("ERROR: isSubsetOf() reports that A^B is not a subset of A"); } if (!A_intersect_B.isSubsetOf(B)) { System.out.println("ERROR: isSubsetOf() reports that A^B is not a subset of B"); } // Verify that A_minus_B is a subset of A if (!A_minus_B.isSubsetOf(A)) { System.out.println("ERROR: isSubsetOf() reports that A-B is not a subset of A"); } // Verify that the intersection of B and A-B is empty. if (!B.intersectionWith(A_minus_B).isEmpty()) { System.out.println("ERROR: isEmpty() reports that B^(A-B) is not empty"); } // Verify that (A - B) U B = A U B if (!A_minus_B.unionWith(B).equals(A_union_B)) { System.out.println("ERROR: equals() reports that (A-B) U B is not A U B"); } } private static void printSet(SetOfPerson set) { System.out.print("Size: " + set.sizeOf() + "; Members: "); set.printNames(); } private static void printMenu() { System.out.println(); System.out.println(QUIT + " (quit)"); System.out.println(ADD + " (test addPerson())"); System.out.println(REMOVE + " (test removePerson())"); System.out.println(OTHERS + " (test others)"); } /* Initializes the global people[] array by putting a bunch ** if People objects into it. */ private static void makePeople() { people = new Person[] { new Person("Andy"), new Person("Ann"), new Person("Barb"), new Person("Bill"), new Person("Carl"), new Person("Carol"), new Person("Dave"), new Person("Diane"), new Person("Emily"), new Person("Ernie"), new Person("Farrah"), new Person("Fred"), new Person("Gail"), new Person("George"), new Person("Hannah"), new Person("Harry"), new Person("Igor"), new Person("Ingrid"), new Person("Jack"), new Person("Jennifer"), new Person("Karen"), new Person("Kevin"), new Person("Larry"), new Person("Lisa"), new Person("Mark"), new Person("Melissa"), new Person("Nancy"), new Person("Nick"), new Person("Olivia"), new Person("Oswald"), new Person("Patty"), new Person("Paul"), new Person("Quinn"), new Person("Quintessa"), new Person("Roger"), new Person("Ruth"), new Person("Sabrina"), new Person("Sam"), new Person("Tara"), new Person("Tom"), new Person("Ulysses"), new Person("Ursula"), new Person("Victoria"), new Person("Vince"), new Person("Walter"), new Person("Wendy"), new Person("Xavier"), new Person("Xena"), new Person("Yannick"), new Person("Yvette"), new Person("Zeke"), new Person("Zelda") }; } /* Prompts the user to enter indices of the people[] array, and returns ** the set whose members are the Person objects at those indices. ** Example: If "9 3 25 47" is entered, the set returned will have as ** members people[9], people[3], people[25], and people[47]. */ private static SetOfPerson userMadeSet() { String prompt = "Make a set by entering indices of people[]: "; String indices = getString(prompt); Scanner indexScanner = new Scanner(indices); SetOfPerson resultSet = new SetOfPerson(); while (indexScanner.hasNext()) { if (indexScanner.hasNextInt()) { int index = indexScanner.nextInt(); if (0 <= index && index < people.length) { resultSet.addPerson(people[index]); } else { System.out.printf("Ignored %d, which is out of range\n", index); } } else { System.out.printf("Ignored %s, which is not an integer numeral\n", indexScanner.next()); } } return resultSet; } /* Returns a string entered in response to the given prompt. */ private static String getString(String prompt) { System.out.print(prompt); String response = input.nextLine(); if (echo) { System.out.println(response); } return response; } /* Returns an integer (in the specified range) entered in response ** to the prompt. Will keep asking until a valid response is provided. */ private static int getInteger(String prompt, int minimum, int maximum) { int result = -1; boolean keepTrying = true; do { try { result = Integer.parseInt(getString(prompt)); if (minimum <= result && result <= maximum) { keepTrying = false; } else { System.out.printf("Error; response must be in range %d..%d;try again\n", minimum, maximum); } } catch (Exception e) { System.out.println("Invalid response; try again..."); } } while (keepTrying); return result; } /* Returns a set of persons of the specified size selected pseudorandomly ** from the persons in people[low..high). The seed is used for seeding ** the instance of Random used in making pseudorandom choices. ** pre: 0 <= low <= high <= people.length && ** 0 <= size <= high - low */ private static SetOfPerson randomPersonSet(int low, int high, int size, int seed) { SetOfPerson result = new SetOfPerson(); Person[] members = randomPermutationOf(low, high, seed); for (int i=0; i != size; i++) { result.addPerson(members[i]); } return result; } /* Returns an array holding a pseudorandom permutation of the elements ** in people[low..high), using 'seed' to seed the Random object used ** in producing the permutation. ** pre: 0 <= low <= high <= ary.length */ private static Person[] randomPermutationOf(int low, int high, int seed) { Random rand = new Random(seed); final int n = high - low; Person[] result = new Person[n]; // copy the elements of people[low..high) into result[]. for (int i=0; i != n; i++) { result[i] = people[low+i]; } // Now pseudorandomly permute the elements of result[] for (int i = result.length; i != 1; i--) { int j = rand.nextInt(i); swap(result, i-1, j); } return result; } /* Swaps the values in the specified locations of the specified array. */ private static void swap(Object[] a, int k, int m) { Object temp = a[k]; a[k] = a[m]; a[m] = temp; } /* Binds the global scanner 'input' to either standard input or to ** the file named by args[0], if that value exists. */ private static void establishScanner(String[] args) { if (args.length == 0) { input = new Scanner(System.in); echo = false; } else { try { input = new Scanner(new File(args[0])); echo = true; } catch (FileNotFoundException e) { System.out.printf("No file named \"%s\" was found; aborting\n", args[0]); System.exit(0); } } } }