AP CSA Practice Exam Section 2 Free Response
Section II: Free Response
4 Questions • 90 Minutes • 50% of Exam Score
- Write your answers clearly in the scratch area below each question. Only the code you write will be graded — not your scratch work.
- Write your solution using Java. You may use any standard Java library methods and constructors that are part of the Java Quick Reference.
- Show all your work. Partial credit is awarded on every question.
- Assume that
importstatements and class declarations are provided where needed. - Click Show Solution only after you have attempted each part completely.
A state motor vehicle department uses a software system to validate license plate codes. A LicensePlate class stores a single plate code as a String. A partial implementation is shown below.
A plate code may contain any combination of letters and digits. Assume plateCode is never null and always has at least one character.
countDigits
4 pts
Write the countDigits method. This method examines each character in plateCode and returns the total number of digit characters ('0' through '9'). Non-digit characters are ignored.
For example:
You may find Character.isDigit(char c) useful. It returns true if c is a digit character.
isValid
5 pts
Write the isValid method. This method returns true if the plate meets all three of the following rules; otherwise it returns false:
- The total length of
plateCodeis between 5 and 8 characters inclusive. - The plate contains exactly 3 digit characters.
- The first character is not a digit.
You must call countDigits in your solution.
For example:
Calling countDigits() is required. A solution that re-implements the digit-counting logic without calling countDigits() does not earn the method-call point.
plateCode using charAt(i) and length() without going out of bounds.Character.isDigit() or an equivalent comparison) and increments a counter for each one found.countDigits() and uses its return value to check that exactly 3 digits are present.charAt(0)) is not a digit using negation.true only when all three conditions are satisfied; returns false in all other cases.Off-by-one in loop: Writing i <= plateCode.length() instead of i < plateCode.length() causes a StringIndexOutOfBoundsException on the last iteration.
Not calling countDigits in Part (b): Re-writing the counting logic from scratch instead of calling countDigits() loses the required method-call point and often introduces new errors.
Missing the “not starts with digit” check: Students often check length and digit count but forget the third condition. Read every precondition carefully.
FRQ 1 almost always requires Part (b) to call the method written in Part (a). Even if your Part (a) solution is slightly wrong, you can still earn full credit on Part (b) if your logic correctly uses the return value of countDigits(). Write Part (b) as if Part (a) works perfectly.
A local animal shelter wants to track the animals in its care. Each animal has a name and a species. When an animal first enters the shelter, it has not yet been vaccinated. The shelter's system needs to be able to mark an animal as vaccinated and check its vaccination status at any time.
The shelter charges an adoption fee that depends on the species. Dogs cost $150, cats cost $100, and all other species cost $75. The fee never changes once set.
Write the complete ShelterAnimal class described below. Your class will be graded on correct encapsulation, constructor behavior, and method implementations.
The ShelterAnimal class must contain:
- Appropriate
privateinstance variables to store the animal's name, species, vaccination status, and adoption fee. - A constructor that takes the animal's name and species as parameters. The constructor must set the vaccination status to not vaccinated and compute the adoption fee based on the species rules described above.
- A
vaccinatemethod that marks the animal as vaccinated. - An
isVaccinatedmethod that returns whether the animal has been vaccinated. - A
getAdoptionFeemethod that returns the adoption fee. - A
toStringmethod that returns aStringwith the animal's name, species, and vaccination status in a readable format of your choosing.
The following code should work correctly with your class:
Note: variable names and exact String format in toString are your design choices — the rubric scores behavior, not names.
private instance variables with correct types for name (String), species (String), vaccination status (boolean), and fee (int or double). Variable names are the student's choice.false (not vaccinated) without being told to do so by a parameter.vaccinate sets vaccination status to true; isVaccinated returns the current vaccination status.getAdoptionFee returns the fee that was set in the constructor.toString returns a String that includes the name, species, and vaccination status in any readable format.Computing fee in getAdoptionFee instead of the constructor: The problem says the fee is set when the animal enters the system (i.e., in the constructor). Recomputing it in the accessor works but misses the design intent — and if a grader is strict, it may cost a point.
Using == to compare Strings: species == "dog" compares object references, not content. Always use .equals() for String comparison in Java.
Making vaccinate() return a value: The method is described as updating state only — the return type should be void.
On the real AP exam, FRQ 2 never tells you what to name your variables. You are graded on whether your class behaves correctly given the described scenario — not on specific variable names. Focus on: private fields, correct constructor logic, and methods that do exactly what the description says.
A WordList class manages a list of words. A partial implementation is shown below.
Assume import java.util.ArrayList; is provided. The words list is never null but may be empty.
removeShorterThan
4 pts
Write the removeShorterThan method. This method removes every String from words whose length is strictly less than minLen.
For example, if words contains ["cat", "elephant", "ox", "dog", "rhinoceros"] and minLen is 4, then after calling removeShorterThan(4), words contains ["elephant", "rhinoceros"].
getUniqueCount
5 pts
Write the getUniqueCount method. This method returns the number of distinct (case-sensitive) strings in words. Duplicates count only once.
For example, if words contains ["apple", "Apple", "apple", "fig", "fig"], this method returns 3 (the distinct strings are "apple", "Apple", and "fig").
You may use an ArrayList as a helper structure. You may not modify the words instance variable.
An enhanced-for loop cannot be used to remove elements from an ArrayList during iteration. The index-based while loop is the standard correct approach.
words elements using .get() and checks .length() correctly against minLen.remove() call (index-based while loop or reverse for loop).minLen (uses <, not <=).words.words and adds each word to the seen list only if it is not already present (uses .contains() or equivalent check; case-sensitive).Enhanced-for during removal: Using a for-each loop and calling words.remove() inside it throws a ConcurrentModificationException. Always use an index-based while loop.
Incrementing after every remove: Writing i++ after every removal skips elements because the ArrayList shifts left when an item is removed.
Modifying words in Part (b): The precondition says do not modify words. Use a separate helper list.
ArrayList removal while iterating is the single most commonly tested ArrayList concept on the AP exam. The while-loop-with-conditional-increment pattern is the expected answer and must be memorized.
A research team collects survey responses on a 1–5 scale. The responses are stored in a 2D array where each row represents one participant and each column represents one survey question. A partial implementation is shown below.
Assume data is always a rectangular 2D array with at least one row and one column. All values in data are integers between 1 and 5 inclusive.
getColumnSum
3 pts
Write the getColumnSum method. This method returns the sum of all values in the column at index col.
For example, if data is {{3, 1, 4}, {1, 5, 9}, {2, 6, 5}} and col is 1, the method returns 12 (the values 1, 5, and 6 in column 1).
hasIncreasingRow
6 pts
Write the hasIncreasingRow method. A row is strictly increasing if each element is greater than the element immediately before it. The method returns true if at least one row is strictly increasing; otherwise false.
For example, given:
hasIncreasingRow() returns true because row 0 is strictly increasing.
If data is {{5, 3, 1}, {4, 4, 4}}, the method returns false.
data.length (number of rows, not columns).data[row][col] with the provided col parameter held constant.data[row][col] to data[row][col-1].true per row and set to false when a non-increasing adjacent pair is found.<= (not just <) to detect both equal and decreasing pairs as violations of strict increase.true immediately upon finding a strictly increasing row; returns false only after all rows are checked and none qualify.Swapping row/col in 2D access: Writing data[col][row] instead of data[row][col] causes an ArrayIndexOutOfBoundsException on non-square arrays.
Using < instead of <=: The condition must be data[row][col] <= data[row][col-1] to correctly reject equal adjacent elements (not strictly increasing).
Inner loop starting at 0: Starting the inner column loop at index 0 causes a comparison to data[row][-1], which throws an exception. Start at index 1.
The boolean flag pattern (assume true, set false when condition fails) is the cleanest way to check a property across an entire row. Early returns in the outer loop are efficient and encouraged — return immediately when the answer is found.
Get in Touch
Whether you're a student, parent, or teacher — I'd love to hear from you.
Just want free AP CS resources?
Enter your email below and check the subscribe box — no message needed. Students get daily practice questions and study tips. Teachers get curriculum resources and teaching strategies.
Message Sent!
Thanks for reaching out. I'll get back to you within 24 hours.
Prefer email? Reach me directly at [email protected]