The first free response question on the 2011 AP Computer Science exam had students work with an array of integers. The values in the array were describing the volume of a sound file. The higher the value, the higher the amplitude.
I liked this one because it didn’t seem as arbitrary as some of the free response questions. It’s close to code that someone might write to solve a real world problem.
Let’s start by looking at the Sound.java
file that holds the two methods you’ll be implementing. I’m stripping out the comments so we can focus on the code part. But it’s probably worth your time to take a look at the full problem.
public class Sound {
private int[] samples;
public int limitAmplitude(int limit) {
// Part A
}
public void trimSilenceFromBeginning() {
// Part B
}
}
The important part here, aside from the methods that we’re going to be implementing, is the samples
instance variable. We’ll need to use that in our solutions.
For part A we’re implementing a method called limitAmplitude
that goes through the samples
instance variable and sets all values that are above or below limit
to that limit.
That part should be relatively easy. Hopefully by the time you’re working on this problem you’ve gone through a bunch of labs working with primitive arrays. What tends to get missed through is that this method also has to return the number of replacements that are made. When we’ve done this as a lab in class it’s returning the value that misses the most points.
public int limitAmplitude(int limit) {
int cnt = 0;
for (int i=0; i<samples.length; i++) {
if (samples[i] > limit) {
samples[i] = limit;
cnt++;
}
else if (samples[i] < -limit) {
samples[i] = -limit;
cnt++;
}
}
return cnt;
}
What I did was create a variable called cnt
that holds the number of replacements. Then the code loops through samples
and compares every value to limit
. If the value is greater than limit
that position is set to limit
and cnt
is incremented. Same goes when the value is less than negative limit
.
Again, we’re working with the primitive array samples
. This time though we’re removing “silence” from the beginning of the array. We’re removing any leading zeros from samples
.
First, we need to know the size of the new array. For that, we need to count leading zeros. And I did that with a while
loop. Normally I would probably abstract out this little piece into a separate method, but you don’t want to do that on the AP exam.
Next the new array gets sized.
We copy everything except the leading zeros from samples
into ray
.
And last we set samples = ray
to update the instance variable.
public void trimSilenceFromBeginning() {
int x = 0;
while (samples[x] == 0) {
x++;
}
int[] ray = new int[samples.length - x];
for (int j=0; j<ray.length; j++) {
ray[j] = samples[j + x];
}
samples = ray;
}
Because the preconditions told us that there would be at least one non-zero value, the first loop can just look for zeros. Otherwise we would have to keep track of where we are in samples
as to not go out of bounds.
The most common mistake I’ve seen on this problem is students not reading the problem and removing all zeros from samples
and not just leading zeros.