EECS2030E Practice Test 1A

PRACTICE

This is a practice test. The actual test may contain fewer or more questions. The actual test may or may not supply you with other materials (such as starter code).

The Java API is here.


Question 1

Implement the utility class described by this API. You do not have to include javadoc comments.

    package test1;
    
    import java.util.ArrayList;
    import java.util.Collections;
    import java.util.HashSet;
    import java.util.List;
    import java.util.Set;
    
    public class Practice1A {
    
        private Practice1A() {
    
        }
    
        /**
         * The string describing this test version.
         */
        public static final String TEST_VERSION = "PRACTICE";
    
        
        public static String hello(String name) {
            return "Hello, " + name;
        }
    
        
        public static String toString(List<Character> t) {
            if (t.isEmpty()) {
                throw new IllegalArgumentException();
            }
            String s = "";
            for (Character c : t) {
                s += c;
            }
            return s;
        }
    
        
        public static List<Character> shuffle(List<Character> t) {
            int n = t.size();
            List<Character> result = new ArrayList<>();
            for (int i = 0; i < n / 2; i++) {
                result.add(t.get(i));
                result.add(t.get(i + n / 2));
            }
            return result;
        }
    
        
        public static List<Character> repeatedChars(String s) {
            List<Character> result = new ArrayList<Character>();
    
            /*
             * This solution uses a set named t to check if a character appears more than
             * once in the string.
             * 
             * Set<Character> t = new HashSet<Character>();
             * for (int i = 0; i < s.length(); i++) { 
             *     char c = s.charAt(i); 
             *     if (t.contains(c) && !result.contains(c)) {
             *         result.add(c);
             *     }
             *     t.add(c);
             * }
             * return result;
             */
    
            /**
             * This solution uses Collections.frequency to count the number of times a
             * character appears in the string.
             */
            List<Character> t = new ArrayList<>();
            for (int i = 0; i < s.length(); i++) {
                char c = s.charAt(i);
                t.add(c);
            }
            for (Character c : t) {
                int n = Collections.frequency(t, c);
                if (n > 1) {
                    if (!result.contains(c)) {
                        result.add(c);
                    }
                }
            }
    
            return result;
        }
    
    }
    


Question 2

Create a text file named answers.txt (use File->New-> Untitled text file in eclipse). Type your answer to the following question in the text file.

A.

Consider the field Practice1A.TEST_VERSION. What does the keyword final mean when used to modify a field?

final when used to modify a field means that the field can only be assigned a value once; it does not necessarily mean that the field is a constant.

B.

Suppose a client writes a main method that includes the following two lines of Java code:

    List<Character> aList = Arrays.asList('g', 'o', 'o', 'd', 'b', 'y', 'e');
    Practice1A.shuffle(aList);
    

The first line of code creates the list ['g', 'o', 'o', 'd', 'b', 'y', 'e'], and the second line of code calls the shuffle method from Question 1.

The memory diagram illustrating the state of memory for the two lines of code is shown below. What suitable values of a, b, and c would complete the memory diagram?

               ---------------------
               |    main method    |
               ---------------------
    aList  100 |        a?         |
               ---------------------
               |                   |
               |                   |
               ---------------------
            b? |    List object    |
               ---------------------
               |                   |
               |                   |
               ---------------------
               | Practice1A.shuffle|
               ---------------------
        t  500 |         c?        |
               ---------------------
    

The address of the List object can be any positive integer value greater than 100 and less than 500; let's pick the value 300. Then we have:

b = 300
a = 300a
c = 300a

In other words, aList and the parameter t (from shuffle) both refer to the same list object which resides at address 300.

C.

Consider the method Practice1A.hello(String) from Question 1. What precondition does the method have? Suppose that as the implementer, you wanted to remove the precondition from Practice1A.hello(String); how could you change your implementation to remove the precondition?

The precondition is stated in the documentation for the parameter name: name must not be equal to null.

Removing the precondition means that the implementer is willing to account for the case that name == null; this usually means that the implementation will first check if name == null and then do the appropriate thing to satisfy the postconditions of the methods. For example, the implementer might choose to state that the postcondition when name == null is to return the string "Hello, stranger".

D.

Provide 3 test cases for the method Practice1A.toString(List<Character>). Make sure that each test case tests a different feature of the method (i.e., don't provide 3 test cases that all check if the correct string was returned). For each test case, provide a one sentence explanation of what the test case is testing.

A test case must state what inputs will be used to run the method, and what the expected results are of running the method with the stated inputs. The question also asks to test different features of the method so you use test cases that test if the correct string is returned, if an exception is thrown when the input list is empty, if an exception is not thrown when the input list is not empty, and if the input list is not modified. It might also be useful to test a boundary case which for this method would be a list of size 1. Five possible test case examples would be:

input: ['a', 'b', 'c']
expected result: string "abc" is returned
explanation: Tests if the expected string is returned for a typical input.

input: the empty list
expected result: IllegalArgumentException is thrown
explanation: Tests if an exception is thrown for an empty list.

input: ['a', 'b', 'c']
expected result: no exception is thrown
explanation: Tests if no exception is thrown for a non-empty list.

input: ['a', 'b', 'c']
expected result: input list is equal to ['a', 'b', 'c'] (after the method is run)
explanation: Tests if the input list remains unchanged.

input: ['a']
expected result: string "a" is returned
explanation: Tests if the expected string is returned for a boundary case.