Lesson 3.4
Sum and average, with an empty-input guard
Part 3: RepetitionReading, about 5 min3 exercises in this lesson, in Python2 exercises in this lesson, in Java
Java answers can't run on Spine yet. You can still read Java, trace it, and put an answer's lines in order.
A running total and an average
By the end of this you will be able to add up values in a loop, work out their average, and keep the program safe when no values were typed at all.
A running total works like a counter, but instead of adding 1 on each turn, it adds the value of that turn. An average needs both: the total of the values, divided by how many there were.
A running total
A student logs how many minutes they practised each day, one number per line, and types done at the end. This program adds them up and counts the days.
total = 0
days = 0
line = input()
while line != "done":
total = total + int(line)
days = days + 1
line = input()
print("Total: " + str(total))import java.util.Scanner;
public static void main(String[] args) {
Scanner scanner
= new Scanner(System.in);
int total = 0;
int days = 0;
String line = scanner.nextLine();
while (!line.equals("done")) {
total = total
+ Integer.parseInt(line);
days = days + 1;
line = scanner.nextLine();
}
System.out.println("Total: " + total);
}The stop value is a word, so each line stays as text until the loop has checked it is not done. Only then is it turned into a number and added. Turning it into a number before the check would fail on the word done.
Here is a trace when the user types 30, 45, 20, then done. Before the loop, total and days are both 0.
| Turn | Number added | total at the end | days at the end |
|---|---|---|---|
| 1 | 30 | 30 | 1 |
| 2 | 45 | 75 | 2 |
| 3 | 20 | 95 | 3 |
Then the line is done, the loop stops, and the program prints Total: 95. Each turn adds the number just read, not 1. That is the only difference from a counter.
The average
The average is the total divided by the count. Work it out after the loop, once, when the total and the count are both final. Dividing inside the loop would give the average of only the days read so far.
For the input above, 95 divided by 3 is 31 with 2 left over. Using whole-number division, as in the lesson on whole-number division, the average is 31: the fraction is dropped. If you write Python, remember that / keeps the fraction and // drops it.
The empty-input guard
Now suppose the very first line is done. The loop never runs, so total is 0 and days is 0. Printing Total: 0 is right: the sum of no numbers is 0. But anything worked out by dividing by days now divides by 0, and dividing a whole number by 0 is not allowed. A program that divides without checking stops with an error about dividing by zero.
The fix is a guard: an if after the loop that checks the count before dividing. Here the program also counts the long days, with 30 minutes or more, and prints what percentage of the days were long. The percentage divides by days, so it sits behind a guard.
total = 0
days = 0
long_days = 0
line = input()
while line != "done":
minutes = int(line)
total = total + minutes
days = days + 1
if minutes >= 30:
long_days = long_days + 1
line = input()
print("Total: " + str(total))
if days == 0:
print("No days")
else:
print("Long days: "
+ str(long_days * 100 // days)
+ "%")import java.util.Scanner;
public static void main(String[] args) {
Scanner scanner
= new Scanner(System.in);
int total = 0;
int days = 0;
int longDays = 0;
String line = scanner.nextLine();
while (!line.equals("done")) {
int minutes
= Integer.parseInt(line);
total = total + minutes;
days = days + 1;
if (minutes >= 30) {
longDays = longDays + 1;
}
line = scanner.nextLine();
}
System.out.println("Total: " + total);
if (days == 0) {
System.out.println("No days");
} else {
System.out.println("Long days: "
+ longDays * 100 / days
+ "%");
}
}For 30, 45, 20, done it prints Total: 95 and then Long days: 66%: two of the three days were long, and 200 divided by 3 is 66 with the fraction dropped. The count of long days is multiplied by 100 first, because 2 divided by 3 as whole numbers is 0. If the first line is done, it prints Total: 0 and then No days, and nothing is divided.
The rule
Keep a total and a count, both starting at 0. Add to both inside the loop. After the loop, check that the count is not 0 before you divide by it. Whenever a program divides by something it counted, ask: can this count be 0?
Now try it yourself on the questions below.
Exercise 3.4.1 · Trace itTrace: sum loop
Complete the trace table for this Python code. [2]
Line 1: total = 0Line 2: n = 1Line 3: while n <= 3:Line 4, indented 1 level: total = total + nLine 5, indented 1 level: n = n + 1Line 6: print(total)
Fill in one row each time a line changes total or n, or prints something. The table already has the right number of rows. In each row, write only what that line changes; you can leave the other cells empty or copy their values down. Write values the way Python shows them: 3 and 3.0 are different, and text goes in quotes. In the output column, write exactly what appears on screen, with no quotes around it.
| Row | total | n | output |
|---|---|---|---|
| 1 | |||
| 2 | |||
| 3 | |||
| 4 | |||
| 5 | |||
| 6 | |||
| 7 | |||
| 8 | |||
| 9 |
Exercise 3.4.23.4.1 · Write itAverage score
Write a program that reads test scores one at a time, stopping at -1, and prints their whole-number average.
- Read one score per line. Every score is a whole number from 0 to 100.
- The value
-1means "no more scores". It is not a score. - If at least one score was entered, print
Average:followed by the average as a whole number (drop the fraction). - If
-1is typed first (no scores at all), printNo scores.
In Python, use // for whole-number division. In Java, / between two ints already drops the fraction.
Your program is run several times. Only what it prints is checked.
Running Java here comes later. You can put this answer's lines in order instead. You can still write your Java answer (it stays while this page is open) and compare it with our worked solution. Or try this exercise in Python.
Examples
Your program is run 7 times: the 3 examples below, and 4 hidden ones that check the rules above. Only what it prints is checked.
three scores, average is 80 (rule 3)
You type
- typed: 80
- typed: 70
- typed: 90
- typed: -1
It prints
Average: 80
no scores at all (rule 4)
You type
- typed: -1
It prints
No scores
one score (rule 3)
You type
- typed: 50
- typed: -1
It prints
Average: 50
Exercise 3.4.33.4.2 · Write itLift distance
Write a program that adds up how many floors a lift travels. It asks for the floors the lift goes to, one at a time, until the user types the word stop, then prints the total.
The lift starts on floor 0. Your program asks for each floor with exactly this prompt, which ends with a colon and one space and no line break:
Next floor:
Each answer is either a whole number, which is the floor the lift moves to, or the word stop. Floors below 0 are basement floors, so -2 is two floors below the ground floor. When the answer is stop, the program prints exactly one line:
Total floors travelled: N
where N is the total number of floors the lift moved, up or down, starting from floor 0 and going to every floor in the order typed.
- A move counts the floors between the floor the lift is on and the next floor, whichever way the lift goes: take the lower floor from the higher one. Moving from floor 2 to floor -1 is 3 floors.
- An answer that is the floor the lift is already on adds 0.
stopends the input: after it, the program asks for nothing more. If the first answer isstop, the program printsTotal floors travelled: 0.- Everything your program prints is checked exactly: every prompt, and the total line with its capital T, its colon and its spaces. What the user types is not part of what your program prints, so each prompt is followed straight away by the next one, and the total line comes right after the last prompt. Spaces at the end of a line are ignored.
- Every answer is either a whole number from -1000 to 1000 or the word
stopin lower case, andstopalways comes.
In Python, write the program at the top level of the file and read each answer with input("Next floor: "). In Java, write the main method, public static void main(String[] args), print each prompt with System.out.print and read each answer with one Scanner. If you paste a whole class instead, its main method is run.
Running Java here comes later. You can put this answer's lines in order instead. You can still write your Java answer (it stays while this page is open) and compare it with our worked solution. Or try this exercise in Python.
Examples
Your program is run 10 times: the 3 examples below, and 7 hidden ones that check the rules above. Only what it prints is checked.
up 5 floors, down 3, then up 4 (rules 1 and 4)
You type
- typed: 5
- typed: 2
- typed: 6
- typed: stop
It prints
Next floor: Next floor: Next floor: Next floor: Total floors travelled: 12
down past the ground floor, then the same floor again (rules 1 and 2)
You type
- typed: 4
- typed: -1
- typed: -1
- typed: stop
It prints
Next floor: Next floor: Next floor: Next floor: Total floors travelled: 9
stop as the first answer (rule 3)
You type
- typed: stop
It prints
Next floor: Total floors travelled: 0