Skip to content
ExamSpine

Lesson 3.3

The counting pattern

Part 3: RepetitionReading, about 4 min2 exercises in this lesson

Java answers can't run on Spine yet. You can still read Java, trace it, and put an answer's lines in order.

The counting pattern

By the end of this you will be able to use a counter to answer "how many times?", and choose whether it counts every turn of a loop or only some of them.

Many questions about a loop start with "how many": how many turns did it take, how many words were typed, how many of them were yes. The answer comes from a counter, a variable that starts at 0 and goes up by 1 each time the thing you are counting happens.

Counting turns

Mia wants to buy a game. She saves 20 every day, starting from nothing. This program reads the price and counts how many days she must save before she has enough.

price = int(input())
saved = 0
days = 0
while saved < price:
    saved = saved + 20
    days = days + 1
print("Days: " + str(days))
import java.util.Scanner;

public static void main(String[] args) {
    Scanner scanner
        = new Scanner(System.in);
    int price = Integer.parseInt(
        scanner.nextLine());
    int saved = 0;
    int days = 0;
    while (saved < price) {
        saved = saved + 20;
        days = days + 1;
    }
    System.out.println("Days: " + days);
}

Here is a trace when the user types 70.

Turnsaved at the startsaved at the enddays at the end
10201
220402
340603
460804

After turn 4 she has 80, so saved < price is false and the loop stops. It prints Days: 4. Two variables change on every turn: saved is what the condition tests, and days is the counter. The counter goes up once per turn, so when the loop ends it holds the number of turns.

The three lines of a counter

A counter has the same shape in every program:

  1. Before the loop: give it a starting value, nearly always 0.
  2. Inside the loop: add 1 when the thing you count happens.
  3. After the loop: use it, for example print it.

Spotting this shape again and again is pattern recognition: once you know it, every new "how many" question starts from the same three lines.

Why 0? Before the first turn, nothing has been counted yet. And a loop can run zero times: if the game is free and the user types 0, then saved < price is false at the first check, the body never runs, and the program prints Days: 0, which is right. Start at 0 unless you can say exactly what has already been counted before the loop begins.

Counting matches

Sometimes you do not want every turn, only the turns where something is true. Then the line that adds 1 goes inside an if. This program reads votes until the word end, and counts both all the votes and the yes votes.

votes = 0
yes = 0
answer = input()
while answer != "end":
    votes = votes + 1
    if answer == "yes":
        yes = yes + 1
    answer = input()
print("Yes: " + str(yes)
    + " of " + str(votes))
import java.util.Scanner;

public static void main(String[] args) {
    Scanner scanner
        = new Scanner(System.in);
    int votes = 0;
    int yes = 0;
    String answer = scanner.nextLine();
    while (!answer.equals("end")) {
        votes = votes + 1;
        if (answer.equals("yes")) {
            yes = yes + 1;
        }
        answer = scanner.nextLine();
    }
    System.out.println("Yes: " + yes
        + " of " + votes);
}

If the user types yes, no, yes, then end, it prints Yes: 2 of 3. The two counters differ only in where their add-1 line sits:

CounterWhere it goes upWhat it counts
votesIn the loop body, outside the ifEvery turn
yesInside the ifOnly turns where the answer is yes

Look at the read at the end of the body. It is outside the if, so it runs on every turn. If it were inside the if, a no vote would never be followed by a new read, and the loop would run forever. That is the missing update from the last lesson, hiding inside an if.

Two common slips

  • Starting at 1 when nothing has been counted yet. The counter is then one too many every time, even when the loop never runs.
  • Adding 1 in the wrong place. Inside the if counts matches, outside it counts turns. Before you write the line, say which one the question asks for.

Now try it yourself on the questions below.

Exercise 3.3.13.3.1 · Write itHalving steps

Write a program that reads a whole number and counts how many times it can be halved (using whole-number division) before it reaches 0.

  1. Read one number on a single line.
  2. Repeatedly divide the number by 2, keeping only the whole-number part, and count each division.
  3. Stop when the number reaches 0.
  4. Print Steps: followed by the count.
  5. If the number is already 0, the count is 0.

The number is always 0 or positive. Your program is run several times. Only what it prints is checked.

In Python, use // for whole-number division. In Java, / between two ints already drops the fraction.

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 6 times: the 3 examples below, and 3 hidden ones that check the rules above. Only what it prints is checked.

  • 8 halves to 4, 2, 1, 0 in four steps (rule 2)

    You type

    1. typed: 8

    It prints

    Steps: 4
  • 1 halves to 0 in one step (rule 2)

    You type

    1. typed: 1

    It prints

    Steps: 1
  • already 0, no steps needed (rule 5)

    You type

    1. typed: 0

    It prints

    Steps: 0
solution.pySolution.java

Exercise 3.3.23.3.2 · Write itCount the digits

Write a function that returns how many digits a whole number has, using a loop that keeps going while there are digits left to count.

  1. n is a whole number from 0 up to 2147483647.
  2. 0 has one digit.
  3. Do not turn the number into text in any way (including f-strings in Python or "" + n in Java), and do not use logarithms. The shortcuts listed with this question are not allowed.

Only the number your function returns is checked.

def digit_count(n: int) -> int

You cannot use these in this question:

  • str()
  • len()
  • repr()
  • format()
  • ascii()
  • .format()
  • .__str__()
  • .__repr__()
  • .__format__()
  • import math
  • import decimal
  • import cmath

This question is about writing a loop that stops at the right time, so turning the number into text or using logarithms is not allowed.

Examples

Your function is tested on 9 cases: the 3 examples below, and 6 hidden ones that check the rules above.

  • digit_count(472) should return 3: three digits
  • digit_count(0) should return 1: zero has one digit (rule 2)
  • digit_count(10) should return 2: the smallest number with two digits

public static int digitCount(int n)

Checking whether Java answers can run here.

You cannot use these in this question:

  • String.valueOf()
  • Integer.toString()
  • Long.toString()
  • String.format()
  • Integer.toUnsignedString()
  • Math.log10()
  • Math.log()
  • .length()
  • .toCharArray()
  • .chars()
  • .codePoints()
  • .split()
  • .getBytes()
  • .charAt()
  • .toString()
  • .precision()
  • .indexOf()
  • import java.math

This question is about writing a loop that stops at the right time, so turning the number into text or using logarithms is not allowed.

Examples

Your function is tested on 9 cases: the 3 examples below, and 6 hidden ones that check the rules above.

  • digitCount(472) should return 3: three digits
  • digitCount(0) should return 1: zero has one digit (rule 2)
  • digitCount(10) should return 2: the smallest number with two digits
solution.pySolution.java