MCQ Review: Practice Test 2

I learnt many valuable skills while taking this College Board Practice MC Exam, including:

Time management during the test (I accidentally spent too long on the initial questions and had to rush towards the end) Code analysis in segments On this MC, I earned a 35/42. My analytics are as follows:


Performance Analysis

Question Topic Skills Time Spent Points
Q14 Comparing Boolean Expressions 2.6 01:06 0/1
Q22 Informal Run-time Analysis 2.12 2:55 0/1
Q23 Implementing Selection and Iteration Algorithms 2.9 01:27 0/1
Q27 Array Traversals 4.4 1:20 0/1
Q34 Anatomy of a Class & Implementing ArrayList Algorithms 3.3 * 4.10 1:25 0/1
Q38 Implementing ArrayList Algorithms 4.10 1:50 0/1
Q41 Informal Run-Time Analysis & Sorting Algorithms 2.12 & 4.15 2:42 0/1

Corrections

Question 14

  • Selected: !a && !b || c
  • Correct Answer: !a || !b || c
  • Explanation: By De Morgan’s law, !(a && b) is equivalent to !a || !b and the entire expression is equivalent to !a || !b || c.

Question 22

  • Selected: “*” is printed n more times than “@”
  • Correct Answer: “*” is printed m more times than “@”
  • Explanation: There are m * n iterations of the loop in Code Segment 1. In Code Segment 2, the outer loop executes m times and the inner loop executes n - 1 times for each iteration of the outer loop. There are m * n - m iterations of the inner loop in code segment 2, so “*” is printed m more times than “@” is printed.

Question 23

  • Selected: The sum of all integers between 1 and num, inclusive
  • Correct Answer: The sum of all odd integers between 1 and num, inclusive
  • Explanation: The variable loop starts at 1 and increments by 2 for each iteration until it is greater than num. The values of loop that are being added together are the odd integers from 1 to num if num is odd or 1 to num - 1 if num is even. In either case, these are the odd integers between 1 and num.

Question 27

  • Selected: 10
  • Correct Answer: 7
  • Explanation: The loop control variable k is initially set to 0 and then incremented by 2 until k is greater than or equal to the length of the array. During the loop, the values of k are 0, 2, 4, and 6. When k has the value 8, the loop terminates since the length of arr is 7. Prior to the loop, x is assigned 0 and then in the body of the loop, the value of arr at index k is added to x. In the first iteration of the loop, when k has the value 0, arr[0] (which is 3) is added to the value of x and x is assigned 3. In the second iteration of the loop, when k has the value 2, arr[2] (which is 1) is added to the value of x and x is assigned 4. In the third iteration of the loop, when k has the value 4, arr[4] (which is 1) is added to the value of x and x is assigned 5. In the fourth and final iteration of the loop, when k has the value 6, arr[6] (which is 2) is added to the value of x and x is assigned 7.

Question 34

  • Selected:
    if (theMajor.equals(k.getMajor())) {
      count++;
    }
    sum += k.getAge();
    
  • Correct Answer:
    if (theMajor.equals(k.getMajor()))
    {
     sum += k.getAge();
     count++;
    }
    
  • Explanation: The method uses an enhanced for loop, so k is a StudentInfo object representing an element in studentList. This code segment compares the string parameter theMajor with the string returned by k.getMajor(). If the two strings are equal, sum is incremented by the value returned by k.getAge() and count is incremented by 1.

Question 38

  • Selected:
    if (bookList.get(b).getPages() > maxPages)
    {
     maxPages = bookList.get(b).getPages();
    }
    
  • Correct Answer:
    if (b.getPages() > maxPages)
    {
     maxPages = b.getPages();
    }
    
  • Explanation: The enhanced for loop traverses bookList and the loop control variable b is assigned Book objects. The if statement compares the value returned by the call b.getPages() to the current value of maxPages. If the returned value is greater than maxPages, maxPages is updated with the new maximum value.

Question 41

  • Selected:
/* Compare values */ /* Assign to temp */
21 times 5 times
  • Correct Answer:
/* Compare values */ /* Assign to temp */
15 times 5 times
  • Explanation: The outer loop iterates one fewer time than the length of the array. The inner loop is dependent on the outer loop, starting at the value of j + 1 and iterating to the end of the array. On the first pass through the outer loop, the inner loop will iterate five times, meaning the /* Compare values / expression will execute 5 times. Each subsequent iteration will result in one fewer iteration of the inner loop. Therefore, the / Compare values / expression is evaluated 5 + 4 + 3 + 2 + 1, or 15, times. The / Assign to temp */ expression is evaluated for every iteration of the outer loop. Therefore, the assignment is made 5 times.

Comparision between the first and second test

Overall, while strong performance in Using Objects & Methods carried Exam 1, Exam 2 shows a well-rounded improvement across all units — most notably a perfect score in Using Objects & Methods and a +18% jump in Class Creation — bringing the total from 28/42 to 35/42.

Reflection & Study Plan

Patterns in My Mistakes

After reviewing my incorrect answers (Q14, Q22, Q23, Q27, Q34, Q38, Q41), I noticed consistent patterns:

  • Boolean Logic: Rushed De Morgan’s Law and didn’t rewrite expressions carefully.
  • Nested Loops & Runtime: Miscounted iterations instead of calculating exact totals.
  • Code Tracing: Didn’t manually trace loops with unusual increments (like += 2).
  • Enhanced For-Loops: Confused object iteration with index-based access.

Overall, my mistakes were mostly precision errors, not conceptual gaps.


Study Focus

Topic Priority Action
Loop & Runtime Analysis High Practice nested loop counting
Code Tracing High Write full iteration tables
Boolean Logic Medium Rewrite logic step-by-step
Enhanced For-Loops Medium Review object vs index loops

Action Plan

  • Redo missed questions without looking at solutions.
  • Practice nested loop counting daily.
  • Trace array updates step-by-step instead of relying on intuition.
  • Slow down slightly on runtime analysis questions.

Final Insight

My understanding is strong — I need better execution discipline.
If I slow down and trace carefully, I can consistently turn these mistakes into full credit.



AP CSA FRQ Practice Set 2 - Review & Reflection

Working through these FRQs showed me that my conceptual understanding is solid. I can analyze a prompt, recognize what it is asking, and map out the logical steps needed to solve it.

When solving an FRQ, I can usually:

  • Identify the goal of the method
  • Determine what needs to be tracked or updated
  • Recognize common patterns (counting, comparing, resetting, traversing)
  • Outline the steps logically before coding

However, I sometimes:

  • Second-guess Java syntax (braces, method structure, return placement)
  • Forget small details like increment placement or condition formatting
  • Lose confidence when writing code from memory instead of recognizing it

This tells me that my issue is not logic — it is fluency. I need more repetition writing full methods by hand so the syntax becomes automatic instead of something I have to consciously recall.


  • RobotMover — random selection, string construction, substring searching (Parts A & B)
  • LapTracker — full class design + state management across method calls
  • PlayerAnalysis — ArrayList traversal + selecting the closest value
  • WordGrid — 2D array traversal + row validation with adjacent comparisons

Reflection: I understand the logic of these FRQs well (I can break down the prompt and plan the algorithm), but I still need more Java syntax fluency when writing complete solutions from memory. I used AI to help comment and clean up my code after I solved each part.


Question 1: RobotMover Class

What the FRQ tested

  • Random number generation with equal probability
  • Building a formatted string inside a loop
  • String searching (indexOf, substring)
  • Correct loop boundaries + overlapping matches
  • Preserving object state (no unintended changes)

The class stores one instance variable:

private String moveSequence;

Formatted like:

move_move_move_...

Part A — Constructor: RobotMover(int numMoves)

Goal: Create numMoves random moves, each followed by "_", with equal chance of: up, down, left, right.

Key idea: generate an integer 0–3 and map it to one of four moves.

public RobotMover(int numMoves)
{
    moveSequence = "";

    String[] moves = {"up", "down", "left", "right"};

    for (int i = 0; i < numMoves; i++)
    {
        int randIndex = (int)(Math.random() * 4);  // 0-3
        moveSequence += moves[randIndex] + "_";
    }
}

Takeaway: I understood the algorithm immediately, but I hesitated on the exact random-number syntax and string-building structure. More repetition writing constructors from scratch will help.


Part B — Method: countOccurrences(String str)

Goal: Return how many times str appears in moveSequence, including overlapping matches (ex: "up_up" appears twice in "up_up_up_").

Strategy: Use indexOf(str, startIndex) and move forward by 1 each time to allow overlaps.

public int countOccurrences(String str)
{
    int count = 0;
    int index = 0;

    while (true)
    {
        int found = moveSequence.indexOf(str, index);

        if (found == -1)
        {
            break;
        }

        count++;
        index = found + 1;  // move by 1 to allow overlapping matches
    }

    return count;
}

Takeaway: My logic was correct, but I needed to slow down and be precise with indexOf + loop control.


Question 2: LapTracker Class

What the FRQ tested

  • Designing a full class with correct instance variables
  • Tracking state across multiple calls
  • Reset logic based on method call count
  • Correct timing of resets

Core concept: This is a state-persistence FRQ: the object must remember what happened across calls.

public class LapTracker
{
    private int resetFrequency;
    private int lapCount;
    private int callCount;

    public LapTracker(int n)
    {
        resetFrequency = n;
        lapCount = 0;
        callCount = 0;
    }

    public int addLaps(int laps)
    {
        // reset happens at the start of a new cycle
        if (callCount == resetFrequency)
        {
            lapCount = 0;
            callCount = 0;
        }

        lapCount += laps;
        callCount++;

        return lapCount;
    }
}

Takeaway: I understood what needed to be tracked (laps + call count), but I still second-guess where the reset should happen. For these FRQs, the order of operations matters as much as the idea.


Question 3: PlayerAnalysis — playerWithClosestScore

What the FRQ tested

  • ArrayList traversal
  • Tracking a “best-so-far” element
  • Using Math.abs() for distance
  • Returning associated data (player ID), not just the score
  • Not modifying the list

Strategy: Linear scan + minimum absolute difference.

public String playerWithClosestScore(int targetScore)
{
    Player closest = playerList.get(0);
    int smallestDiff = Math.abs(closest.getScore() - targetScore);

    for (int i = 1; i < playerList.size(); i++)
    {
        Player current = playerList.get(i);
        int diff = Math.abs(current.getScore() - targetScore);

        if (diff < smallestDiff)
        {
            smallestDiff = diff;
            closest = current;
        }
    }

    return closest.getID();
}

Takeaway: My main weakness here is not the algorithm—it’s confidence with loop bounds and writing the “tracking two things” pattern quickly (closest object + best diff).


Question 4: WordGrid — countOrderedRows

What the FRQ tested

  • 2D array traversal
  • Adjacent comparisons within a row
  • Boolean flag pattern (assume true → invalidate if broken)
  • Early exit with break
  • Correct indexing (start at col 1, compare to col - 1)

Definition: A row is ordered if string lengths are non-decreasing:

length(current) >= length(previous)
public int countOrderedRows()
{
    int count = 0;

    for (int row = 0; row < grid.length; row++)
    {
        boolean ordered = true;

        for (int col = 1; col < grid[row].length; col++)
        {
            if (grid[row][col].length() < grid[row][col - 1].length())
            {
                ordered = false;
                break;
            }
        }

        if (ordered)
        {
            count++;
        }
    }

    return count;
}

Takeaway: The logic is straightforward for me, but writing nested loops cleanly (without missing braces/conditions) is still something I need to practice.


FRQ Patterns I’m Building

Across all four FRQs, I repeatedly used these core patterns:

  • Random selection: (int)(Math.random() * n)
  • String building in loops: += with consistent formatting
  • Substring searching: indexOf(str, start) + careful index updates
  • State management: multiple instance variables working together
  • Min/closest tracking: keep “best-so-far” + update condition
  • 2D traversal: row loop outside, column loop inside
  • Row/sequence validation: boolean flag + early break

What I Did Well

  • I can read a prompt and quickly identify the required algorithm.
  • I can explain each solution in plain language before writing code.
  • I recognize common FRQ patterns (counting, searching, resetting, comparing).

What I Need to Improve

1) Java Syntax Fluency

I need more repetition writing from memory:

  • method headers + return types
  • for-loops and nested loops
  • braces/indentation consistency
  • common built-in calls (Math.random, Math.abs, indexOf, .size())

2) Speed + Confidence Under Pressure

Even when I know the logic, I slow down because I:

  • second-guess small syntax details
  • worry about missing parentheses/braces
  • hesitate on loop boundaries and condition placement

Goal: Make the structure automatic so the logic can show clearly.


Next Steps

  • Write full FRQ methods from scratch (no copying) until syntax feels automatic
  • Do timed practice focusing on:
    • nested loops
    • state-tracking classes
    • substring searching with overlaps
  • After each FRQ, check:
    • loop boundaries
    • reset/order-of-operations
    • whether I returned the correct value (ID vs score, etc.)

Overall: This set confirmed my logic is strong — my biggest improvement area is turning that logic into clean Java quickly and confidently.