Computer Science A
2018 FRQ Q1
- Question Overview
- FrogSimulation class Specification
- Key Insights
- Code Runner Challenge
- Example of successful simulation
- Example of failed simulation
- Solution Explanation
- Part (a): simulate() - 5 Points
- Objective for Part (a):
- Code Runner Challenge
- How It Works
- Popcorn Hack #2
- Part (b): runSimulations(int num) - 4 Points
- Objective for Part (b):
- Code Runner Challenge
- How It Works
- Popcorn Hack #3
- Scoring Guidelines
- Homework FRQ 2017 Q1!
Question Overview
This question involves simulating a frog attempting to reach a goal distance by hopping along to said distance. You will implement two methods for the FrogSimulation class.
FrogSimulation class Specification
-
goalDistance= (target position) -
maxHops` = (maximum hops allowed)
-
hopDistance()= A private method that returns the distance of a single hop (can be positive, negative, or zero) -
simulate()Returns true if the frog reaches the goal without going negative; false otherwise -
runSimulations(int num)Runs num simulations and returns the proportion of successful attempts as a double
Key Insights
- The frog starts at position 0
- After each hop, check if position < 0 (fail immediately) or position >= goalDistance (succeed immediately)
- For
runSimulations, use(double) successes / numto avoid integer division
Code Runner Challenge
FrogSimulation
View IPYNB Source
// CODE_RUNNER: FrogSimulation
// This class models a frog trying to reach goalDistance in at most maxHops.
class FrogSimulation {
private int goalDistance;
private int maxHops;
// Constructor stores FRQ parameters: target distance and hop limit.
public FrogSimulation(int dist, int numHops) {
goalDistance = dist;
maxHops = numHops;
}
// Returns one random hop in the range -2 to 8 inclusive.
private int hopDistance() {
return (int) (Math.random() * 11) - 2; // -2 to 8
}
// Part (a): simulate one trial and report success/failure.
public boolean simulate() {
int position = 0; // Frog starts at position 0.
for (int i = 0; i < maxHops; i++) {
position += hopDistance(); // Update position after each hop.
if (position < 0) {
return false; // Immediate failure if frog goes negative.
}
if (position >= goalDistance) {
return true; // Immediate success once goal is reached/passed.
}
}
return false; // Used all hops without reaching goal.
}
// Part (b): run many trials and return success proportion.
public double runSimulations(int num) {
int successes = 0;
for (int i = 0; i < num; i++) {
if (simulate()) {
successes++; // Count successful simulations.
}
}
return (double) successes / num; // Cast to avoid integer division.
}
}
public class Main {
public static void main(String[] args) {
FrogSimulation sim = new FrogSimulation(24, 5);
System.out.println("Single simulation: " + sim.simulate());
System.out.println("Proportion successful in 1000 runs: " + sim.runSimulations(1000));
}
}
Main.main(null);
Example of successful simulation
Given: goalDistance = 24, maxHops = 5, Hop sequence: 5, 7, -2, 8, 6
| Hop | Distance | Position | Negative? | Goal? | Result |
|---|---|---|---|---|---|
| 1 | 5 | 5 | No | No | Continue |
| 2 | 7 | 12 | No | No | Continue |
| 3 | -2 | 10 | No | No | Continue |
| 4 | 8 | 18 | No | No | Continue |
| 5 | 6 | 24 | No | Yes (24 >= 24) | Return true |
What you should see when you run the code:
- Single simulation: true or false (varies due to randomness)
- Proportion: approximately 0.3-0.5 (varies)
Example of failed simulation
Given: goalDistance = 24, maxHops = 5, Hop sequence: 6, -7, …
| Hop | Distance | Position | Negative? | Goal? | Result |
|---|---|---|---|---|---|
| 1 | 6 | 6 | No | No | Continue |
| 2 | -7 | -1 | Yes | N/A | Return false |
Key Point: The simulation ends immediately when the frog goes negative. Remaining hops are not executed.
Popcorn Hack #1
Question: In the code above, why is
positioncreated insidesimulate()instead of being stored as an instance variable of the class? Explain how this choice helps each simulation run behave correctly.
Show answer
`position` should reset to 0 every time `simulate()` is called, because each run represents a new trial. Making it a local variable keeps each simulation independent, while an instance variable could accidentally carry position from one run into the next and produce incorrect results.Solution Explanation
Below is the complete implementation that satisfies all 9 points on the rubric for parts (a) and (b)
Part (a): simulate() - 5 Points
Objective for Part (a):
Write the simulate() method so it models one frog run starting at position 0. The method should update the position after each hop, return false immediately if the frog goes below 0, return true immediately if the frog reaches or passes the goal, and return false if the frog uses all allowed hops without reaching the goal.
Code Runner Challenge
Solution Example Part (a) - simulate()
View IPYNB Source
// CODE_RUNNER: Solution Example Part (a) - simulate()
//Given Code
class FrogSimulation {
private int goalDistance;
private int maxHops;
private int[] testHops;
private int hopIndex;
public FrogSimulation(int dist, int numHops, int[] hops) {
goalDistance = dist;
maxHops = numHops;
testHops = hops;
hopIndex = 0;
}
// Deterministic hop provider for testing instead of random hops.
private int hopDistance() {
if (hopIndex < testHops.length) {
return testHops[hopIndex++];
}
return 0;
}
// Start of part (a)
public boolean simulate() {
int position = 0; // Start point.
for (int i = 0; i < maxHops; i++) {
position += hopDistance();
if (position < 0) {
return false; // Fail immediately if below 0.
}
if (position >= goalDistance) {
return true; // Succeed immediately at/above goal.
}
}
return false; // Did not reach goal within max hops.
}
}
public class Main {
public static void main(String[] args) {
FrogSimulation successCase = new FrogSimulation(24, 5, new int[]{5, 7, -2, 8, 6});
FrogSimulation failCase = new FrogSimulation(24, 5, new int[]{6, -7, 8, 8, 8});
System.out.println("Expected true: " + successCase.simulate());
System.out.println("Expected false: " + failCase.simulate());
}
}
Main.main(null);
How It Works
- Initialize position to 0
- Loop exactly
maxHopstimes - Update position with
hopDistance() - Check if position < 0 and return
falseimmediately - Check if position >= goalDistance and return
trueimmediately - Return
falseafter loop if goal not reached
Popcorn Hack #2
Question: Why must the method check for failure (
position < 0) and success (position >= goalDistance) during each hop instead of waiting until all hops finish? Explain how this supports the simulation rules.
Show answer
Part (a) models a run that can end the moment an outcome is decided. Checking each hop enforces the rules exactly: a run fails immediately when position goes negative and succeeds immediately when the goal is reached. Waiting until the end could misclassify runs by ignoring early stop conditions.Part (b): runSimulations(int num) - 4 Points
Objective for Part (b):
Write the runSimulations(int num) method so it runs the simulation num times, counts how many runs succeed, and returns the proportion of successful runs as a double.
Code Runner Challenge
Solution Example Part (b) - runSimulations(int num)
View IPYNB Source
// CODE_RUNNER: Solution Example Part (b) - runSimulations(int num)
//Given Code
class FrogSimulation {
private int goalDistance;
private int maxHops;
private int[][] trials;
private int trialIndex;
private int hopIndex;
public FrogSimulation(int dist, int numHops, int[][] allTrials) {
goalDistance = dist;
maxHops = numHops;
trials = allTrials;
trialIndex = 0;
hopIndex = 0;
}
private int hopDistance() {
if (trialIndex >= trials.length) return 0;
int[] currentTrial = trials[trialIndex];
if (hopIndex < currentTrial.length) return currentTrial[hopIndex++];
return 0;
}
// Included from part (a) to run
public boolean simulate() {
if (trialIndex >= trials.length) return false;
int position = 0;
hopIndex = 0; // Reset hop pointer for this trial.
for (int i = 0; i < maxHops; i++) {
position += hopDistance();
if (position < 0) {
trialIndex++; // Move to next trial after this run.
return false;
}
if (position >= goalDistance) {
trialIndex++; // Move to next trial after this run.
return true;
}
}
trialIndex++;
return false;
}
// Start of part (b)
public double runSimulations(int num) {
int successes = 0;
for (int i = 0; i < num; i++) {
if (simulate()) successes++;
}
return (double) successes / num; // Decimal success rate.
}
}
public class Main {
public static void main(String[] args) {
int[][] sampleTrials = {
{5, 7, -2, 8, 6}, // success
{6, -7, 8, 8, 8}, // fail (bc goes negative)
{8, 8, 8, 0, 0}, // success
{1, 1, 1, 1, 1} // fail (dosen't reach goal in time)
};
FrogSimulation sim = new FrogSimulation(24, 5, sampleTrials);
System.out.println("Expected 0.5: " + sim.runSimulations(4));
}
}
Main.main(null);
How It Works
simulate()tracks the frog’s position starting from 0, updating after each hop- The method returns immediately when the frog goes negative or reaches the goal
runSimulations(int num)callssimulate()multiple times and calculates the success rate- Casting to
doubleis essential to get a decimal proportion instead of 0
Popcorn Hack #3
Question: If two students run different numbers of trials, why is success proportion a better metric than number of successes, and why is casting to
doubleessential for reporting that metric accurately?
Show answer
Part (b) compares performance across many runs, so proportion is equal even when trial counts differ. Raw counts are not directly comparable (for example, 40/100 vs 40/200). Casting to `double` preserves decimal precision so the reported success rate reflects the true ratio instead of just integer division.Scoring Guidelines
Points Breakdown (9 points total)
Part (a): simulate() (5 points)
- 1 point: Initializes position variable to 0
- 1 point: Loops exactly
maxHopstimes - 1 point: Calls
hopDistance()and updates position - 1 point: Checks if position < 0 inside loop and returns
falseimmediately - 1 point: Checks if position >= goalDistance inside loop and returns
true; returnsfalseafter loop
Part (b): runSimulations(int num) (4 points)
- 1 point: Initializes counter to 0
- 1 point: Loops
numtimes - 1 point: Calls
simulate()and increments counter when true - 1 point: Returns
(double) successes / num
Common Mistakes to Avoid
- Checking conditions outside the loop instead of inside
- Using
==instead of>=for goal check - Using
position <= 0instead ofposition < 0 - Not casting to double:
successes / numgives 0 instead of proportion - Not returning immediately when conditions are met