On a recent final exam I had students create a method that could interleave two halves of an array. The original exercise came from a Schaum's Outline book. If you're not careful, by passing values by reference you can have the student's solution pollute the original input test value. To solve this in Java you can clone a copy of the test input prior to passing it into the student's method.
The original question is this:
* Perform a perfect shuffle on an array that is submitted to your method. * This is like a perfect shuffle of a deck of cards. Interleave the first half of * the array with the second half of the array. (Source)
Here is a reference solution
public class TeacherReferenceSolutions {
/* Method 1 for the Teacher (it's the answer) */
public int[] teacherMethod(int[] originalArray){//, int checkValue) {
int n = originalArray.length;
int m = n/2;
int i = 0;
int j = m;
int k = 0;
int[] outputArray = new int[n];
while(i < m){
outputArray[k++] = originalArray[i++];
outputArray[k++] = originalArray[j++];
}
// System.arraycopy(outputArray,0,originalArray,0,k);
return outputArray;
}
}
Here is the Java jUnit test.
import org.junit.Assert;
import org.junit.Test;
import javax.swing.*;
import java.util.*;
import java.util.List;
public class TheTestClass {
@Test
// method
public void testOne() {
TeacherReferenceSolutions theReference = new TeacherReferenceSolutions();
StudentSolution theStudentAttempt = new StudentSolution();
int[] studentAnswer;
int[] teacherAnswer;
final int MIN_INPUT = -10; // Boundaries on inputs (max, min)
final int MAX_INPUT = +20;
final int TEST_TOTALNUMBER = 5; // Number of sub-tests run on student vs. teacher.
final int LENGTH_ROWVECTOR = 10; // number of entries in each row vector.
final int thresholdValue = new Random().nextInt(MAX_INPUT - MIN_INPUT) + MIN_INPUT; // this is the max value to be compared against.
int[] oneRowVector = new int[LENGTH_ROWVECTOR];
ArrayList<int[]> allTestArrays = new ArrayList<>();
// Populate an ArrayList of row vectors. Each row vector is a new test set.
for(int i = 0; i < TEST_TOTALNUMBER; i++){
for(int j = 0; j < LENGTH_ROWVECTOR; j++){
oneRowVector[j] = new Random().nextInt(MAX_INPUT - MIN_INPUT) + MIN_INPUT;
}
allTestArrays.add(oneRowVector); // add one row at a time.
}
// Make a copy of the test array and make it immutable. (doesn't work in current version of JDK with VPL)
// https://docs.oracle.com/en/java/javase/11/core/creating-immutable-lists-sets-and-maps.html#GUID-DB0865D2-C052-40BC-A3DC-20FCB3088DC9
// List<int[]> ALL_TEST_ARRAYS = List.copyOf(allTestArrays);
/* -----------------------------------
* First loop. Print to screen messages that students can more easily decode.
* ----------------------------------- */
for (int testIteration = 0; testIteration < TEST_TOTALNUMBER; testIteration++) {
// extract an integer array for testing (one per row).
int[] singleRowVectorInput = allTestArrays.get(testIteration);
/* Run the teacher solution once. Get the reference output. */
int[] clonedCopyInputForTeacher = singleRowVectorInput.clone();
teacherAnswer = theReference.teacherMethod(clonedCopyInputForTeacher);
System.out.println("Subtest " + testIteration + " : testing against inputs : \t\t\t"
+ Arrays.toString(singleRowVectorInput) );
// Run the student's answer. Get the student's output. */
int[] clonedCopyInputForStudent = singleRowVectorInput.clone();
studentAnswer = theStudentAttempt.studentMethod(clonedCopyInputForStudent);
try {
Assert.assertArrayEquals(teacherAnswer, studentAnswer);
System.out.println("Sub-Test " + testIteration + " _passed_. Testing against inputs : \t" + Arrays.toString(singleRowVectorInput));
System.out.println("Teacher solution: " + Arrays.toString(teacherAnswer) +
" ... versus student solution: " + Arrays.toString(studentAnswer));
System.out.println("------------------------------------------------------");
System.out.println("");
} catch (AssertionError e) {
System.out.println("");
System.out.println("****************************************************");
System.out.println("vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv");
System.out.println("\n\t\t\t Sub-Test " + testIteration + " + DID NOT PASS!! \t\t\t\t");
System.out.println("For inputs \t\t\t\t\t\t\t\t\t\t" + Arrays.toString(singleRowVectorInput));
System.out.println("Sub-Test " + testIteration + " FAILED. Testing against inputs : \t" + Arrays.toString(singleRowVectorInput));
System.out.println("We have teacher solution " + Arrays.toString(teacherAnswer) +
" & student output: " + Arrays.toString(studentAnswer));
System.out.println(e.getMessage());
System.out.println("");
System.out.println("^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^");
System.out.println("****************************************************");
System.out.println("");
}
}
/* ---------------------------------------------
* Second loop. Allows jUnit to register the error in VPL or in the IDE.
* ---------------------------------------------- */
for (int testIteration = 0; testIteration < TEST_TOTALNUMBER; testIteration++) {
// extract an integer array for testing (one per row).
int[] singleRowVectorInput = allTestArrays.get(testIteration);
/* Run the teacher solution once. Get the reference output. */
int[] clonedCopyInputForTeacher = singleRowVectorInput.clone();
teacherAnswer = theReference.teacherMethod(clonedCopyInputForTeacher);
System.out.println("Subtest " + testIteration + " : testing against inputs : " + Arrays.toString(singleRowVectorInput) );
// Run the student's answer. Get the student's output. */
int[] clonedCopyInputForStudent = singleRowVectorInput.clone();
studentAnswer = theStudentAttempt.studentMethod(clonedCopyInputForStudent);
// no try-catch here. This will register with the IDE or VPL
Assert.assertArrayEquals(teacherAnswer, studentAnswer);
}
} // end method
}
James Andrew Smith is a Professional Engineer and Associate Professor in the Electrical Engineering and Computer Science Department of York University's Lassonde School, with degrees in Electrical and Mechanical Engineering from the University of Alberta and McGill University. Previously a program director in biomedical engineering, his research background spans robotics, locomotion, human birth and engineering education. While on sabbatical in 2018-19 with his wife and kids he lived in Strasbourg, France and he taught at the INSA Strasbourg and Hochschule Karlsruhe and wrote about his personal and professional perspectives. James is a proponent of using social media to advocate for justice, equity, diversity and inclusion as well as evidence-based applications of research in the public sphere. You can find him on Twitter. Originally from Québec City, he now lives in Toronto, Canada.