Part A: simulate()

import java.util.Random;

class FrogSimA {
    private int goalDistance = 24;
    private int maxHops = 5;
    private Random rand = new Random(42);

    public int hopDistance() {
        return rand.nextInt(16) - 5; // range: -5 to 10
    }

    public boolean simulate() {
        int position = 0;
        for (int i = 0; i < maxHops; i++) {
            position += hopDistance();
            if (position < 0) {
                return false;
            }
            if (position >= goalDistance) {
                return true;
            }
        }
        return false;
    }
}

public class PartA {
    public static void main(String[] args) {
        FrogSimA frog = new FrogSimA();
        for (int i = 1; i <= 5; i++) {
            System.out.println("Run " + i + ": " + frog.simulate());
        }
    }
}
PartA.main(null);
Run 1: false
Run 2: false
Run 3: false
Run 4: true
Run 5: false

Each call is a single independent simulation. The frog succeeded on run 4 and failed the rest — either by going negative or exhausting all 5 hops without reaching position 24.

Part B: runSimulations(int num)

import java.util.Random;

class FrogSimB {
    private int goalDistance = 24;
    private int maxHops = 5;
    private Random rand = new Random();

    public int hopDistance() {
        return rand.nextInt(16) - 5; // range: -5 to 10
    }

    public boolean simulate() {
        int position = 0;
        for (int i = 0; i < maxHops; i++) {
            position += hopDistance();
            if (position < 0) {
                return false;
            }
            if (position >= goalDistance) {
                return true;
            }
        }
        return false;
    }

    public double runSimulations(int num) {
        int successes = 0;
        for (int i = 0; i < num; i++) {
            if (simulate()) {
                successes++;
            }
        }
        return (double) successes / num;
    }
}

public class PartB {
    public static void main(String[] args) {
        FrogSimB frog = new FrogSimB();
        System.out.println("Success proportion: " + frog.runSimulations(1000));
    }
}
PartB.main(null);
Success proportion: 0.149

Out of 1000 simulations, about 14.9% succeeded. This makes sense given how difficult it is to reach position 24 in only 5 hops with random distances ranging from -5 to 10 — the frog needs consistently large positive hops without any negative ones tanking the run early.

Key Takeaways

  • Loop-based simulation: simulate() uses a for loop bounded by maxHops — not a while(true) — so it naturally terminates after a fixed number of hops.
  • Early exit conditions: Return false immediately when position goes negative (fell in water); return true immediately when position meets or exceeds the goal. Don’t wait for the loop to finish.
  • Reusing methods: runSimulations() simply calls simulate() repeatedly and counts successes — no need to reimplement the hop logic. Reuse existing methods on the object.
  • Proportion vs. count: The return type of runSimulations() is double, so cast before dividing: (double) successes / num. Integer division would return 0 almost always.
  • Off-by-one awareness: The hop range is -5 to 10 inclusive (rand.nextInt(16) - 5), and the goal check is >= goalDistance, not >. Make sure boundary conditions match the problem spec exactly.