Java Arena
Step 6 of 7

A class that remembers

Objects are good at remembering. A class can collect numbers one at a time and answer questions about them whenever it's asked: how many there have been, their total, their average, the largest. This log of bike trips does that:

Main.java
public class Main {
    public static void main(String[] args) {
        TripLog log = new TripLog();
        log.add(12);
        log.add(40);
        log.add(5);
        System.out.println("Trips: " + log.tripCount());
        System.out.println("Total: " + log.totalKm() + " km");
        System.out.println("Longest: " + log.longestKm() + " km");
        System.out.println("Average: " + log.averageKm() + " km");
    }
}
TripLog.java
public class TripLog {
    private int count;
    private int total;
    private int longest;

    public TripLog() {
        this.count = 0;
        this.total = 0;
        this.longest = 0;
    }

    public void add(int km) {
        this.count++;
        this.total = this.total + km;
        if (km > this.longest) {
            this.longest = km;
        }
    }

    public int tripCount() {
        return this.count;
    }

    public int totalKm() {
        return this.total;
    }

    public int longestKm() {
        return this.longest;
    }

    public double averageKm() {
        if (this.count == 0) {
            return 0.0;
        }
        return (double) this.total / this.count;
    }
}
Output
Trips: 3
Total: 57 km
Longest: 40 km
Average: 19.0 km
  • The log doesn't keep the trips themselves, only what it needs for its answers: how many trips, their sum, and the longest so far. Each add updates all three. (Later in the course, an object gets a list of its own.)
  • The average isn't stored: averageKm() works it out when it's asked, from the count and the total. (double) turns the total into a double before the division, so the decimals aren't lost (module 4).
  • averageKm() checks for an empty log first. With no trips there's no average, and the method returns 0.0 instead of dividing by zero.

The class does the bookkeeping, and main only gives it numbers and asks questions. The same class works whether the numbers are written in the code, as here, or typed in by a user. What a log like this remembers depends on the questions it has to answer: the challenges below keep track of other things than a count and a total.

Your task

Challenge 1 of 3

A RainLog collects the rainfall of each day, in millimeters. Write its methods: add(int mm) records one day's rain, dryDays() returns how many days had no rain at all, and wettest() returns the most rain on a single day (0 before any rain). The instance variables are ready, and add keeps both of them up to date. The check records 4, 0, 11 and 0 mm:

2 dry days, wettest 11 mm

Challenge 2

A dry spell is a run of dry days in a row. Add a method longestDrySpell() that returns the most dry days in a row so far (0 when there hasn't been a dry day). The log has to remember two more things: how many dry days in a row there have been up to now, and the longest run so far. Add instance variables for them, and update them in add: a dry day makes the current run one day longer, and a day with rain ends it. The check records 3, 0, 0 and 5 mm and asks, then records 0, 0, 0 and 2 mm and asks again:

2
3

Challenge 3

Now use the finished RainLog in a program that gives a one-line verdict on the weather. Read the rain of each day, one number per line, until an empty line, and add each number to a RainLog. Then print one line:

  • Drought warning: and the longest dry spell followed by dry days in a row, when the longest dry spell is 3 days or more;
  • otherwise Flood watch: and the wettest day's rain followed by mm in one day, when the wettest day had 20 mm or more;
  • otherwise Normal weather.

For the input 0, 0, 4, 0, 0, 0, 1 and an empty line, the program prints:

Drought warning: 3 dry days in a row