CompSci.rocks
FRQcsapa

Account: 2026 FRQ 1

A step-by-step solution to the 2026 AP CSA FRQ 1 (Account), covering retrying a value with a loop until a helper method accepts it and stripping characters out of a String around a delimiter in Java.

Picking a username that isn't already taken is the everyday problem behind this AP Computer Science A free-response question — first retrying variations of a requested name until one sticks, then cleaning up a chosen name by stripping out its hyphens.

What This FRQ Tests

  • AP CSA units: Unit 3 (Boolean Expressions and if Statements), Unit 4 (Iteration), and Unit 5 (Writing Classes/methods)
  • Core skill: looping with a "keep trying until a helper method says yes" pattern
  • Secondary skill: scanning a String one position at a time and deciding, based on what comes next, whether to keep or drop the current character
  • Official category: "Methods and Control Structures" — always FRQ 1 on the AP CSA exam

The Setup

  • Account holds:
    • private String username — set once, in the constructor
  • A helper method is already provided and not to be modified:
    • static boolean isAvailable(String str) — is this username free to take?
  • You're asked to write two members:
    • Account(String requestedName) — picks a real, available username based on requestedName
    • String getShortenedName() — returns username with every hyphen and the character right before it removed

Part (a): Writing the Account Constructor

The Rule, Broken Down

  1. If requestedName is already available, just use it.
  2. Otherwise, try requestedName followed by 1, then 2, then 3, and so on, until one of them is available.
  3. Whichever variation is first found available becomes username.

Step-by-Step Approach

  1. Start with candidate equal to requestedName itself, and a counter starting at 1.
  2. Loop for as long as candidate is not available.
  3. Each time through, build the next candidate by appending the current counter value to requestedName, then increment the counter.
  4. Once the loop finds an available candidate, store it in username.

The Code

public Account(String requestedName)
{
    String candidate = requestedName;
    int suffix = 1;

    while (!isAvailable(candidate))
    {
        candidate = requestedName + suffix;
        suffix++;
    }

    username = candidate;
}

Why Each Piece Matters

  • candidate starts as requestedName itself, with no suffix — this is what correctly handles the case where requestedName is already available, without needing a separate check before the loop.
  • The loop condition is !isAvailable(candidate) — the loop keeps running for as long as the current candidate is unavailable, stopping the moment one finally is.
  • candidate = requestedName + suffix, always built from requestedName, never from the previous candidate — each retry appends a number directly to the original requested name ("Luis-Cruz1", "Luis-Cruz2", ...), not to whatever the last failed attempt was.
  • suffix increments every time through the loop, starting at 1 — this produces the exact sequence "1, 2, 3, ..." the problem describes.

Tracing the Example

Using the question's own examples:

  • requestedName = "PSmith", already available: the loop condition !isAvailable("PSmith") is false immediately, so the loop never runs — username becomes "PSmith" directly. Matches.
  • requestedName = "Luis-Cruz", not available: candidate starts as "Luis-Cruz" (unavailable) → try "Luis-Cruz1" → if still unavailable, try "Luis-Cruz2" → and so on, until an available one is found. Matches the question's described retry sequence exactly.

Common Mistakes to Avoid

  • Starting the suffix at 0 instead of 1, which would try "Luis-Cruz0" first instead of "Luis-Cruz1".
  • Appending the suffix to the previous candidate instead of the original requestedName, which would produce nonsense like "Luis-Cruz11" or "Luis-Cruz12" instead of "Luis-Cruz1", "Luis-Cruz2".
  • Not handling the "already available" case separately, and instead always appending at least 1 — this would incorrectly turn an available "PSmith" into "PSmith1".
  • Forgetting to call isAvailable at all and just assigning requestedName directly — the problem explicitly requires using it "appropriately" for full credit.

Part (b): Writing getShortenedName()

The Rule, Broken Down

  1. Scan username from left to right.
  2. Every time a hyphen is found, remove it and the character immediately before it.
  3. Every other character stays, in its original relative order.
  4. If there are no hyphens at all, the method just returns username unchanged.

Step-by-Step Approach

  1. Walk through username one position at a time, using a manually controlled index (since a hyphen removal consumes two characters at once, not one).
  2. At each position, check whether the next character is a hyphen.
  3. If it is, skip the current character entirely (it's about to be removed along with the hyphen), and jump the index forward by two — past both the current character and the hyphen.
  4. If it isn't, keep the current character and move the index forward by just one.
  5. Keep going until the index reaches the end of username.

The Code

public String getShortenedName()
{
    String result = "";
    int i = 0;

    while (i < username.length())
    {
        if (i + 1 < username.length() && username.substring(i + 1, i + 2).equals("-"))
        {
            i = i + 2;
        }
        else
        {
            result = result + username.substring(i, i + 1);
            i++;
        }
    }

    return result;
}

Why Each Piece Matters

  • A while loop with a manually managed index, not a simple for loop — the amount the index advances by is different depending on whether a hyphen was just found (2) or not (1), which a for loop's fixed i++ can't express on its own.
  • i + 1 < username.length(), checked before looking ahead — this guards against checking one character past the end of the string on the very last character, which the precondition (no trailing hyphen) actually already rules out, but the check keeps the logic safe regardless.
  • username.substring(i + 1, i + 2), not charAt(i + 1)charAt isn't part of the method subset this solution sticks to; pulling out a one-character String with substring and comparing it with .equals("-") does the same job.
  • Jumping i forward by 2 on a hyphen, rather than 1 — this is what actually removes both the character before the hyphen and the hyphen itself, since neither one ever gets appended to result.

Tracing the Example

Using username = "Amy-Marie-Lin" (length 13):

i Character Next is -? Action result so far
0 A no append, i → 1 "A"
1 m no append, i → 2 "Am"
2 y yes skip both, i → 4 "Am"
4 M no append, i → 5 "AmM"
5 a no append, i → 6 "AmMa"
6 r no append, i → 7 "AmMar"
7 i no append, i → 8 "AmMari"
8 e yes skip both, i → 10 "AmMari"
10 L no append, i → 11 "AmMariL"
11 i no append, i → 12 "AmMariLi"
12 n (no next char) append, i → 13 "AmMariLin"

Final result: "AmMariLin" — matches the question exactly. And for a username with no hyphens at all (like "SammyB3"), the "next is -" check never succeeds, so every character just gets appended unchanged, correctly returning the original string.

Common Mistakes to Avoid

  • Incrementing i by only 1 after skipping a hyphen pair. This would re-visit the hyphen itself on the next iteration and accidentally append it, instead of removing it.
  • Checking username.substring(i, i + 1).equals("-") (the current character) instead of checking the next one — the rule removes a hyphen and the character before it, which means the decision to skip has to be made one character early.
  • Using charAt instead of substring. Both work in real Java, but charAt isn't on the AP Quick Reference sheet, so this solution sticks to substring for the character-by-character comparisons.
  • Forgetting the i + 1 < username.length() bounds check before looking at the next character, which risks an index-out-of-bounds error on the last character of the string.

Key Takeaways

  • "Keep trying variations until a helper method accepts one" is a while (!helperMethod(candidate)) loop — build the next candidate inside the loop body, always from the original input, not the last failed attempt.
  • Removing a pattern that spans more than one character (like "a character and the hyphen after it") needs a manually controlled loop index, since different iterations need to advance by different amounts.
  • substring(i, i + 1) is the standard stand-in for charAt(i) when only substring is available — extracting a one-character window works the same way either method is written.

Related FRQs