2024 FRQ 4 Solution + Explanation

This took me a bit yayayayayayay

public class Feeder
{
    // instance variable: amount of food in grams currently in the bird feeder
    private int currentFood;

    /**
     * constructor to initialize the feeder with a starting amount of food
     */
    public Feeder(int startingFood)
    {
        currentFood = startingFood;
    }

    /**
     * simulates one day with numBirds birds or possibly a bear at the bird feeder
     * precondition: numBirds > 0
     */
    public void simulateOneDay(int numBirds)
    {
        int chanceValue = (int)(Math.random() * 100);

        // 5% chance a bear visits (0-4 out of 100)
        if (chanceValue < 5)
        {
            currentFood = 0;
        }
        else
        {
            // normal conditions: birds visit
            // each bird eats a random amount from 10 to 50 grams (inclusive)
            int gramsPerBird = (int)(Math.random() * 41) + 10;
            
            // Total food birds want to eat
            int totalEaten = gramsPerBird * numBirds;
            
            // update currentFood
            if (totalEaten > currentFood)
            {
                currentFood = 0;
            }
            else
            {
                currentFood -= totalEaten;
            }
        }
    }

    /**
     * returns the number of days birds or a bear found food to eat at the feeder
     * in this simulation
     * preconditions: numBirds > 0, numDays > 0
     */
    public int simulateManyDays(int numBirds, int numDays)
    {
        int daysWithFood = 0;

        // Simulate up to numDays days
        for (int day = 0; day < numDays; day++)
        {
            // if feeder is empty, stop simulation early (no food to find)
            if (currentFood <= 0)
            {
                break;
            }

            // simulate one day and increment counter
            simulateOneDay(numBirds);
            daysWithFood++;
        }

        return daysWithFood;
    }

    /**
     * getter method to check current food level
     */
    public int getCurrentFood()
    {
        return currentFood;
    }
}

// Test cases
Feeder feeder = new Feeder(500);
System.out.println("Testing Part A - simulateOneDay:");
System.out.println("Starting food: " + feeder.getCurrentFood() + " grams");
feeder.simulateOneDay(12);
System.out.println("After 1 day with 12 birds: " + feeder.getCurrentFood() + " grams");

System.out.println("\nTesting Part B - simulateManyDays:");
Feeder feeder2 = new Feeder(1000);
System.out.println("Starting food: " + feeder2.getCurrentFood() + " grams");
int days = feeder2.simulateManyDays(10, 20);
System.out.println("Days with food: " + days);
System.out.println("Remaining food: " + feeder2.getCurrentFood() + " grams");
Testing Part A - simulateOneDay:
Starting food: 500 grams
After 1 day with 12 birds: 296 grams

Testing Part B - simulateManyDays:
Starting food: 1000 grams
Days with food: 4
Remaining food: 0 grams

How I Solved This Problem

What’s Actually Happening

This problem simulates a bird feeder where birds (and occasionally a bear) come to eat. The challenge is to model:

  1. Part A: What happens on a single day
  2. Part B: How many days the feeder can sustain visitors

The key twist: 5% of the time a bear shows up and eats everything. Otherwise, normal birds visit.

Part A Solution: simulateOneDay(int numBirds)

The Logic:

  1. Generate a random chance (0-99)
  2. If it’s 0-4 (5% chance): A bear visits → currentFood = 0
  3. Otherwise (95% chance): Birds visit
    • Each bird eats the same random amount: 10-50 grams
    • Calculate total eaten: gramsPerBird × numBirds
    • If total eaten > currentFood: set currentFood to 0 (feeder emptied)
    • Otherwise: subtract total from currentFood

Key Implementation Details:

// 5% bear check
int chanceValue = (int)(Math.random() * 100);
if (chanceValue < 5) {
    currentFood = 0;
} else {
    // random grams per bird: 10-50 inclusive
    int gramsPerBird = (int)(Math.random() * 41) + 10;
    int totalEaten = gramsPerBird * numBirds;
    
    // can't eat more than available
    if (totalEaten > currentFood) {
        currentFood = 0;
    } else {
        currentFood -= totalEaten;
    }
}

Part B Solution: simulateManyDays(int numBirds, int numDays)

The Logic:

  1. Create a counter: daysWithFood = 0
  2. Loop up to numDays times:
    • Before each day: Check if feeder is empty (currentFood ≤ 0)
    • If empty: break out of loop (stop simulation)
    • If there’s food: call simulateOneDay(numBirds) and increment counter
  3. Return the count of days where food was available

Key Implementation Details:

int daysWithFood = 0;
for (int day = 0; day < numDays; day++) {
    // Check BEFORE simulating the day
    if (currentFood <= 0) {
        break;  // No food left, stop early
    }
    
    // Simulate one day
    simulateOneDay(numBirds);
    daysWithFood++;
}
return daysWithFood;

Why This Design?

The Order Matters:

  • We check if currentFood <= 0 before calling simulateOneDay
  • This ensures we only count days where visitors actually found food
  • If the feeder empties on day 5, we stop and return 5 (not 6)

Example Walkthrough:

  • Start: 300 grams, want to simulate 5 days with 8 birds
  • Day 1: 300g available → simulate → maybe 250g left, daysWithFood = 1
  • Day 2: 250g available → simulate → maybe 0g left, daysWithFood = 2
  • Day 3: 0g available → break immediately (feeder is empty)
  • Return: 2 days with food

Test Cases to Verify

Part A Test:

  • Feeder with 500g, 12 birds, normal day should leave ~240-540g
  • Feeder should never go negative

Part B Test:

  • Start with 1000g, simulate 10 days with 5 birds
  • Should return days until food runs out
  • Stopping early if feeder empties saves computation