CompSci.rocks
FRQcsapa

APCalendar: 2019 FRQ 1

A step-by-step solution to the 2019 AP CSA FRQ 1 (APCalendar), covering a counting loop and combining two given helper methods to compute a day of the week in Java.

Calendars hide a surprising amount of arithmetic behind a simple question like "what day of the week was this?" This AP Computer Science A free-response question asks you to count leap years across a range, then combine two given helper methods to work out a day of the week without writing any date logic of your own.

What This FRQ Tests

  • AP CSA units: Unit 3 (Boolean Expressions and if Statements), Unit 4 (Iteration), Unit 5 (Writing Classes/methods)
  • Core skill: writing a counting loop that calls a boolean helper method once per iteration
  • Secondary skill: combining two independent helper methods' results with plain arithmetic instead of re-deriving their logic
  • Official category: "Methods and Control Structures" — always FRQ 1 on the AP CSA exam

The Setup

  • APCalendar is a utility class — every method is static, and there are no instance variables at all.
  • private static boolean isLeapYear(int year) — given, not to modify.
  • public static int numberOfLeapYears(int year1, int year2) — part (a).
  • private static int firstDayOfYear(int year) — given; returns 0-6 for the weekday January 1 fell on.
  • private static int dayOfYear(int month, int day, int year) — given; returns which numbered day of the year a date is (Jan 1 = 1), already accounting for leap years.
  • public static int dayOfWeek(int month, int day, int year) — part (b).

Part (a): Writing numberOfLeapYears(int year1, int year2)

Step-by-Step Approach

  1. Start a counter at 0.
  2. Loop over every year from year1 to year2, inclusive.
  3. Call isLeapYear(year) on each one.
  4. If it returns true, increment the counter.
  5. Return the counter after the loop ends.

The Code

public static int numberOfLeapYears(int year1, int year2)
{
    int count = 0;

    for (int year = year1; year <= year2; year++)
    {
        if (isLeapYear(year))
        {
            count++;
        }
    }

    return count;
}

Why Each Piece Matters

  • year <= year2, not < — the precondition says the range is inclusive, so year2 itself must be checked, never skipped.
  • Calling isLeapYear(year) instead of reimplementing leap-year logic — the question's real rubric explicitly requires using the helper "appropriately" to receive full credit. isLeapYear already exists and is assumed correct; there's no reason (and no credit) for rewriting the "divisible by 4, not by 100 unless by 400" rule inline.
  • count only changes inside the if block — years that aren't leap years simply pass through the loop with no effect on the total.

Tracing the Example

The released question doesn't give a numeric example for this specific method, but it's easy to self-check using a small range: numberOfLeapYears(2016, 2019).

Year isLeapYear(year) Running count
2016 true 1
2017 false 1
2018 false 1
2019 false 1

The loop returns 1 — the only leap year in that range is 2016, which checks out.

Common Mistakes to Avoid

  • Using < instead of <=. This silently skips year2, undercounting by one whenever year2 itself happens to be a leap year.
  • Reimplementing the leap-year rule inline instead of calling isLeapYear. Even if the logic is correct, it ignores the instruction to use the helper, and risks getting the actual rule (the "divisible by 100 but not 400" exception) subtly wrong.
  • Starting count at 1 out of habit — there's no reason to assume the range starts on a leap year.

Part (b): Writing dayOfWeek(int month, int day, int year)

The Rule, Broken Down

  1. firstDayOfYear(year) tells you which weekday (0-6) January 1 fell on that year.
  2. dayOfYear(month, day, year) tells you which numbered day of the year this date is (January 1 is day 1).
  3. Since day 1 falls on weekday firstDayOfYear(year) exactly, every day after that shifts the weekday forward by one, wrapping every 7 days.

Step-by-Step Approach

  1. Get the year's starting weekday: first = firstDayOfYear(year).
  2. Get this date's day number within the year: n = dayOfYear(month, day, year).
  3. Day 1 corresponds to weekday first exactly, so day n corresponds to weekday first + (n - 1) — the -1 because day 1 itself shouldn't add any offset.
  4. Wrap that sum into the valid 0-6 range with % 7.

The Code

public static int dayOfWeek(int month, int day, int year)
{
    int first = firstDayOfYear(year);
    int n = dayOfYear(month, day, year);

    return (first + n - 1) % 7;
}

Why Each Piece Matters

  • n - 1 counts how many days after January 1 this date is — day 1 itself should add zero days, not one.
  • Adding that offset to first shifts the year's starting weekday forward by the right number of days.
  • % 7 keeps the result inside the valid 0-6 range no matter how large first + n - 1 gets — a year has up to 366 days, so the raw sum can be far bigger than 7, and it needs to wrap around correctly.

Tracing the Example

The question states firstDayOfYear(2019) returns 2 (2019 began on a Tuesday), and gives two worked calls:

Call first n (dayOfYear) first + n - 1 % 7 Expected
dayOfWeek(1, 5, 2019) 2 5 6 6 6
dayOfWeek(1, 10, 2019) 2 10 11 4 4

Both match the question's stated return values exactly — 6 (Saturday) and 4 (Thursday).

Common Mistakes to Avoid

  • Forgetting the - 1. Adding first + n directly overcounts by one day, since day 1 shouldn't add any offset at all.
  • Applying % 7 at the wrong step — the full sum first + n - 1 needs to be computed first, then reduced mod 7, not the other way around.
  • Trying to recompute the day-of-year or first-day-of-year logic manually instead of calling the two given helper methods. Both are already provided, correct, and exactly what "must use firstDayOfYear and dayOfYear appropriately" is asking for.

Key Takeaways

  • "Inclusive" in a precondition is a direct signal to use <=, not <, in a loop's bound.
  • When a problem hands you working helper methods, the intended solution almost always combines their results with simple arithmetic rather than re-deriving their logic yourself.
  • Modular arithmetic (% 7 for weekdays, or % n for any fixed-size cycle) is the standard tool for wrapping a running offset back into a valid range.

Related FRQs