Computer Science A
2017 FRQ 3
- FRQ Question 3
- FRQ Question Part A
- FRQ Question Part B
- FRQ Question Part A
- Part (a):
replaceNthOccurrenceMethod - FRQ Question Part B
- Part (b):
findLastOccurrenceMethod - Scoring Guidelines
- Alternative Solution for Part (b)
- Quick Edge Tests
- Key Points to Remember
FRQ Question 3
This question involves the Phrase class, which contains methods for working with phrases and finding/replacing occurrences of strings within them.
You will write two methods for the Phrase class:
- Part (a):
replaceNthOccurrence - Part (b):
findLastOccurrence
Both methods will use the provided findNthOccurrence method.
Analyze the Problem: Walkthrough
String Searching and Manipulation
Problem Type: String processing / loops / method calls
Difficulty: Medium
You are given a
Phraseobject that contains:
currentPhrase(String) - the phrase being worked withfindNthOccurrence(String str, int n)- finds the nth occurrence of a substringYou must implement:
- Replace the nth occurrence of a substring with another string (
replaceNthOccurrence)- Find the last occurrence of a substring (
findLastOccurrence)
Mental Model
Think of the phrase as a text document you’re searching through:
findNthOccurrence(str, n)is like a search function that jumps to the nth matchreplaceNthOccurrence(str, n, repl)finds and replaces the nth occurrencefindLastOccurrence(str)keeps searching forward until no more matches exist
Checkpoint: Before coding, make sure you can answer:
- What does
findNthOccurrencereturn when the nth occurrence doesn’t exist?- How do you split a string at a specific index and reconstruct it with a replacement?
- How do you keep searching for occurrences until you’ve found the last one?
FRQ Question Part A
Part (a): replaceNthOccurrence Method
Write the Phrase method replaceNthOccurrence, which will replace the nth occurrence of the string str with the string repl. If the nth occurrence does not exist, currentPhrase remains unchanged.
Requirements:
- You must use
findNthOccurrenceappropriately to receive full credit - If the nth occurrence does not exist,
currentPhraseremains unchanged - The method modifies
currentPhrase(it’s a void method)
Examples:
Phrase phrase = new Phrase("A cat ate late.");
phrase.replaceNthOccurrence("at", 1, "ot");
// currentPhrase becomes "A cot ate late."
phrase = new Phrase("A cat ate late.");
phrase.replaceNthOccurrence("at", 6, "xx");
// currentPhrase unchanged (6th occurrence doesn't exist)
Walkthrough (How to Think About It)
Step 1: Find the nth occurrence
- Call
findNthOccurrence(str, n)to get the index - Store the result in a variable
Step 2: Check if replacement should occur
- If
findNthOccurrencereturns-1, the occurrence doesn’t exist - Only proceed with replacement if a valid index is returned
Step 3: Construct the new phrase
- Get everything before the occurrence:
currentPhrase.substring(0, index) - Add the replacement string:
repl - Get everything after the occurrence:
currentPhrase.substring(index + str.length()) - Combine all three parts and assign back to
currentPhrase
Common pitfall: Don’t forget that after finding the occurrence at
index, the original substring has lengthstr.length(), notrepl.length().
FRQ Question Part B
Part (b): findLastOccurrence Method
Write the Phrase method findLastOccurrence. This method finds and returns the index of the last occurrence of a given string in currentPhrase. If the given string is not found, -1 is returned.
Requirements:
- You must use
findNthOccurrenceappropriately to receive full credit - Returns the index of the last occurrence of the string
- Returns
-1if the string is not found - The
currentPhrasemust not be modified
Examples:
Phrase phrase = new Phrase("A cat ate late.");
phrase.findLastOccurrence("at"); // returns 11 (in "late")
phrase = new Phrase("A cat ate late.");
phrase.findLastOccurrence("bat"); // returns -1 (not found)
Walkthrough (How to Think About It)
Step 1: Set up a loop to find successive occurrences
- Start with
occurrence = 1 - Call
findNthOccurrence(str, 1), thenfindNthOccurrence(str, 2), etc.
Step 2: Keep track of the last valid occurrence found
- Store each valid index as you find it
- When you get
-1, you know the previous index was the last one
Step 3: Handle the case where no occurrences exist
- If the first call to
findNthOccurrence(str, 1)returns-1, return-1immediately
Algorithm Approaches:
Approach 1: Keep searching until you hit -1
Code Runner Challenge
AP CSA 2017 FRQ - Phrase
View IPYNB Source
occurrence = 1
lastFound = -1
while true:
index = findNthOccurrence(str, occurrence)
if index == -1:
return lastFound
lastFound = index
occurrence++
Approach 2: Look ahead
occurrence = 1
index = findNthOccurrence(str, occurrence)
while index != -1:
occurrence++
nextIndex = findNthOccurrence(str, occurrence)
if nextIndex == -1:
return index
index = nextIndex
return -1
Key insight: You need to keep calling
findNthOccurrencewith increasing values ofnuntil it returns-1, meaning no more occurrences exist.
FRQ Question Part A
Part (a):replaceNthOccurrence Method
Write the Phrase method replaceNthOccurrence, which will replace the nth occurrence of the string str with the string repl. If the nth occurrence does not exist, currentPhrase remains unchanged.
Requirements:
- You must use
findNthOccurrenceappropriately to receive full credit. - If the nth occurrence does not exist,
currentPhraseremains unchanged.
FRQ Question Part B
Part (b): findLastOccurrence Method
Write the Phrase method findLastOccurrence. This method finds and returns the index of the last occurrence of a given string in currentPhrase. If the given string is not found, -1 is returned.
Requirements:
- You must use
findNthOccurrenceappropriately to receive full credit. - Returns the index of the last occurrence of the string.
- Returns
-1if the string is not found. - The
currentPhrasemust not be modified.
// CODE_RUNNER: AP CSA 2017 FRQ - Phrase
public class Phrase {
private String currentPhrase;
/** Constructor */
public Phrase(String p) {
currentPhrase = p;
}
/** Returns the index of the nth occurrence of str */
public int findNthOccurrence(String str, int n) {
int count = 0;
int index = 0;
while (index <= currentPhrase.length() - str.length()) {
int found = currentPhrase.indexOf(str, index);
if (found == -1) {
return -1;
}
count++;
if (count == n) {
return found;
}
index = found + 1; // Move to next position (not found + str.length())
}
return -1;
}
/** PART (a): replaceNthOccurrence */
public void replaceNthOccurrence(String str, int n, String repl) {
int index = findNthOccurrence(str, n);
if (index != -1) {
currentPhrase = currentPhrase.substring(0, index) + repl +
currentPhrase.substring(index + str.length());
}
}
/** PART (b): findLastOccurrence */
public int findLastOccurrence(String str) {
int occurrence = 1;
int lastIndex = -1;
while (true) {
int index = findNthOccurrence(str, occurrence);
if (index == -1) {
return lastIndex;
}
lastIndex = index;
occurrence++;
}
}
/** Getter for testing */
public String toString() {
return currentPhrase;
}
/* There may be instance variables, constructors, and methods that are not shown. */ }
// CODE_RUNNER: AP CSA 2017 FRQ - Phrase
public class Main {
private String currentPhrase;
/** Constructor */
public Main(String p) {
currentPhrase = p;
}
/** Returns the index of the nth occurrence of str */
public int findNthOccurrence(String str, int n) {
int count = 0;
int index = 0;
while (index <= currentPhrase.length() - str.length()) {
int found = currentPhrase.indexOf(str, index);
if (found == -1) {
return -1;
}
count++;
if (count == n) {
return found;
}
index = found + str.length();
}
return -1;
}
/** PART (a): replaceNthOccurrence */
public void replaceNthOccurrence(String str, int n, String repl) {
int index = findNthOccurrence(str, n);
if (index != -1) {
currentPhrase =
currentPhrase.substring(0, index)
+ repl
+ currentPhrase.substring(index + str.length());
}
}
/** PART (b): findLastOccurrence */
public int findLastOccurrence(String str) {
int n = 1;
int last = -1;
while (findNthOccurrence(str, n) != -1) {
last = findNthOccurrence(str, n);
n++;
}
return last;
}
public void driver() {
System.out.println("Original phrase: " + currentPhrase);
replaceNthOccurrence("hello", 2, "hi");
System.out.println("After replaceNthOccurrence: " + currentPhrase);
int lastIndex = findLastOccurrence("world");
System.out.println("Last occurrence of 'world': " + lastIndex);
}
/** Main entry point */
public static void main(String[] args) {
Main tester = new Main("hello world hello world");
tester.driver();
}
}
Main.main(null);
Scoring Guidelines
Part (a): replaceNthOccurrence - 4 points
Calling findNthOccurrence - 1 point
- Calls
findNthOccurrence(str, n)with appropriate parameters
Determining if replacement should occur - 1 point
- Uses the result from
findNthOccurrenceto determine whether the nth occurrence exists - Typically checks if the returned index is not
-1
Constructing the new phrase - 2 points
- 1 point: Uses
substringto get the part ofcurrentPhrasebefore the nth occurrence - 1 point: Uses
substringto get the part ofcurrentPhraseafter the nth occurrence - Combines these parts with
replin the correct order - Assigns the result back to
currentPhrase
Sample Solution:
public void replaceNthOccurrence(String str, int n, String repl) {
int index = findNthOccurrence(str, n);
if (index != -1) {
currentPhrase = currentPhrase.substring(0, index) + repl +
currentPhrase.substring(index + str.length());
}
}
Part (b): findLastOccurrence - 5 points
Calling findNthOccurrence in a loop - 2 points
- 1 point: Calls
findNthOccurrencewith appropriate parameters - 1 point: Calls
findNthOccurrencemultiple times in a loop to find successive occurrences
Loop continuation condition - 1 point
- Loop continues while occurrences of
strare still being found - Typically checks if
findNthOccurrencereturns-1
Tracking the last occurrence found - 1 point
- Stores/tracks the index of occurrences as they are found
- Maintains the most recent valid index
Returning the correct value - 1 point
- Returns the index of the last occurrence when no more occurrences exist
- Returns
-1if no occurrences are found
Sample Solution:
public int findLastOccurrence(String str) {
int occurrence = 1;
int lastIndex = -1;
while (true) {
int index = findNthOccurrence(str, occurrence);
if (index == -1) {
return lastIndex;
}
lastIndex = index;
occurrence++;
}
}
Alternative Solution for Part (b)
public int findLastOccurrence(String str) {
int occurrence = 1;
int index = findNthOccurrence(str, occurrence);
while (index != -1) {
occurrence++;
int nextIndex = findNthOccurrence(str, occurrence);
if (nextIndex == -1) {
return index;
}
index = nextIndex;
}
return -1;
}
Why these approaches work
Part (a):
findNthOccurrencedoes the hard work of finding where to replace- We just need to rebuild the string:
[before] + [replacement] + [after] - The check for
-1ensures we don’t modify the phrase when the occurrence doesn’t exist
Part (b):
- By incrementally calling
findNthOccurrence(str, 1), thenfindNthOccurrence(str, 2), etc., we walk through all occurrences - When we get
-1, we know the previous occurrence was the last one - The loop naturally handles the case where no occurrences exist (returns
-1on first call)
Quick Edge Tests
// Edge case: overlapping occurrences
Phrase p = new Phrase("aaaa");
System.out.println(p.findLastOccurrence("aa")); // 2
p.replaceNthOccurrence("aa", 1, "b");
System.out.println(p); // "baa"
// Edge case: single character
Phrase p2 = new Phrase("hello");
System.out.println(p2.findLastOccurrence("l")); // 3
p2.replaceNthOccurrence("l", 2, "L");
System.out.println(p2); // "heLlo"
// Edge case: not found
Phrase p3 = new Phrase("hello");
System.out.println(p3.findLastOccurrence("z")); // -1
p3.replaceNthOccurrence("z", 1, "x");
System.out.println(p3); // "hello" (unchanged)
Key Points to Remember
- Use
findNthOccurrence: Both parts require you to call this method - don’t reimplement the search logic - Handle
-1properly: Check for-1before attempting any string manipulation - Index arithmetic: When removing a substring, remember to skip
str.length()characters, notrepl.length() - Loop strategy: For Part (b), keep incrementing the occurrence counter until you get
-1 - Overlapping occurrences:
findNthOccurrenceshould increment by 1, not bystr.length(), to catch overlapping matches