Skip to content

Exercise 9 of 10 · Putting it together

Rainfall Week

What you will make

A seven-day rainfall chart with a row for every day, the week added up underneath it, and the wettest of the seven days picked out.

The one new idea: A variable created above a loop carries a running value from one pass to the next

Adding up as you go, and holding on to the best you have seen, are two patterns sitting underneath an enormous number of ordinary programs: a basket total, a high score, a longest streak, a progress bar. Each one is a variable created before a loop and changed inside it.

Go straight to the code ↓

A variable that outlives one turn of the loop

There is no new syntax in this exercise. An array, a for-each loop, an if, String.format, + — you have met every piece of it. That is the point. Knowing five things separately is not the same as getting them to work together in one program, and the gap between those two is where most people stall.

The idea that joins them up is small. A variable created above a loop is still standing on every turn, and still standing after the loop ends, so whatever one turn leaves in it is what the next turn finds. Put the line that sets its starting value inside the loop's braces instead, and that line runs again every time round, throwing away whatever the turn before it left there. Anything the loop must carry from one day to the next has to be created above it.

Two things are worth carrying that way here.

A running total. Create a variable set to 0 above the loop, and inside it write total = total + mm;. Java works out the right-hand side first — whatever total was a moment ago, plus this turn's value — and puts the answer back under the same name. After seven turns it holds the sum of all seven.

The best so far. Create a second variable set to 0 above the loop, then inside it ask whether this turn beats it: if (mm > wettestMm) {. When it does, store the new number. That variable then holds the largest value seen up to that moment — and by the final turn, the largest so far is simply the largest there is.

Remembering which day was wettest is one more line, not a new idea: inside the same if, store the day alongside the amount. They change together because they are one fact in two halves.

A worked example

Four coins out of a jar, with the total printed on every turn so you can watch it climb:

Java
public class Main {
    public static void main(String[] args) {
        int[] coins = {2, 5, 1, 5};
        int total = 0;
        int biggest = 0;
        for (int coin : coins) {
            total = total + coin;
            if (coin > biggest) {
                biggest = coin;
            }
            System.out.println("coin " + coin + "  total " + total);
        }
        System.out.println("biggest coin: " + biggest);
    }
}
Output
coin 2  total 2
coin 5  total 7
coin 1  total 8
coin 5  total 13
biggest coin: 5

total never drops back to 0, because the line that sets it to 0 sits above the loop and runs once, before any counting starts. biggest ends on 5 — and notice it does not change on the last turn, even though that coin is a 5 too: 5 > 5 is false, so a tie leaves the first one in place.

Your turn

The editor holds a week of rainfall. rain is an array of seven measurements in millimetres, and the for-each loop prints a row for each one: a day number, a bar of one # per millimetre, and the measurement. Day two was dry, so its bar has no # in it at all and the row looks half empty. That is correct, not broken — zero millimetres draws zero hashes.

Press Run first. The chart is correct; the two lines beneath it are not. The total reads 0 mm, and the wettest day comes out as day 0, which is not one of the seven.

Both of your additions go inside the loop's braces, after the println that is already there.

  1. Add this day's rain to total.
  2. If this day beats wettestMm, store both the new amount and the day number.

total, wettestMm and wettestDay already exist above the loop, all holding 0: you are not creating them, only changing them as the loop goes round. The counter day = day + 1; is a running total too, so the shape of your first line is already on screen.

If something goes wrong

The likeliest slip is placement. A line sitting after the loop's closing brace is outside it, and worse, it tries to use mm — a name that only exists inside those braces — so javac stops with cannot find symbol before the program runs at all.

If the millimetres come out right but the day stays at 0, the if is updating wettestMm and forgetting wettestDay. Both lines belong inside the if, indented one step further than the if itself.

If the message mentions incompatible types: int cannot be converted to boolean, the comparison was written with one equals sign instead of two — or > was meant instead of either.

Nothing here can break. Once the week adds up, change one of the numbers in rain and run it again: the bar, the total and the wettest day should all move on their own.

Write your code

Runs in your browser. Press Run (or Ctrl/Cmd+Enter) and the output is checked for you.

Ctrl/Cmd+Enter to run

Press Esc then Tab to move keyboard focus out of the code editor.

Ready
Output will appear here after you run your code.

The runtime is starting in the background. You can type now — it will be ready before you are.

The answer appears here once you have run your code at least once.

Things that often go wrong here

Writing total = total + mm; below the loop instead of inside its braces
A line placed after the loop's closing brace runs once, after every day has already gone past — and by then mm is not available at all, because a for-each loop's variable exists only inside the braces it was declared in. javac reports cannot find symbol for mm on that line, before the program ever runs.
Setting total back to 0 inside the loop
int total = 0; placed on the first line of the loop's body runs again on every single day, wiping out whatever the days before it had added — so the whole week adds up to day seven's rain alone. A starting value belongs above the loop, where the line that sets it runs exactly once.
Remembering the amount but not the day
An if that only updates wettestMm leaves wettestDay holding the zero it started with, so the last line claims the wettest day was day 0, which is not one of the seven. Both lines belong inside the same if, because they are two halves of one fact — the day that broke the record, and the amount that broke it.
Writing if (mm = wettestMm)
One equals sign is an instruction to store a value, not a question, and its result is an int rather than a boolean. javac refuses the whole program before anything runs, reporting incompatible types: int cannot be converted to boolean. The comparison this exercise needs is not equals anyway — it is greater than.

Want a blank editor instead? Open the Java playground.