20. Loop patterns — Homework solutions

The .go solution files are in exercises/20/homework/solutions/.

Problem 1 — Factorial

Problem. Multiply 1 through 5 together.

How to think about it. Accumulate, but with *= instead of +=. Start the product at 1. Start at 0 and the answer is 0, since anything times zero is zero.

Worked solution.

package main

import "fmt"

func main() {
    product := 1
    for i := 1; i <= 5; i++ {
        product *= i
    }
    fmt.Println(product)
}

Output:

120

Problem 2 — Count multiples

Problem. Count numbers from 1 to 50 that divide evenly by 7.

How to think about it. Count pattern: the test is i%7 == 0, and the tally is hits++.

Worked solution.

package main

import "fmt"

func main() {
    hits := 0
    for i := 1; i <= 50; i++ {
        if i%7 == 0 {
            hits++
        }
    }
    fmt.Println(hits)
}

Output, counting 7, 14, 21, 28, 35, 42, and 49:

7

Problem 3 — First big square

Problem. Find the first number whose square is over 200.

How to think about it. Search pattern. first starts at -1, a value that can never be the answer, and the loop stops at the first match.

Worked solution.

package main

import "fmt"

func main() {
    first := -1
    for i := 1; i <= 100; i++ {
        if i*i > 200 {
            first = i
            break
        }
    }
    fmt.Println(first)
}

14 × 14 is 196, and 15 × 15 is 225, so the output is:

15

Common mistakes.

  • Forgetting break, so the loop runs on and first lands on the last match, not the first.
  • Declaring first inside the loop. It would then not exist after the loop, and Go stops with undefined: first.

Challenge — Range stats in one pass

Problem. Total, even-count, and a divisible-by-9 flag from one loop.

How to think about it. Three variables before the loop, one line or one if for each inside it, and three prints after it.

Worked solution.

package main

import "fmt"

func main() {
    total := 0
    evens := 0
    hasNine := false

    for i := 1; i <= 20; i++ {
        total += i
        if i%2 == 0 {
            evens++
        }
        if i%9 == 0 {
            hasNine = true
        }
    }

    fmt.Println("total", total)
    fmt.Println("evens", evens)
    fmt.Println("divisible by 9", hasNine)
}

Output, where the flag flips at 9 and stays true through 18:

total 210
evens 10
divisible by 9 true

Common mistakes.

  • Writing three separate loops over the same range. One pass does all three jobs, which is why it pays to spot the patterns.
  • Using else if between the two tests. A number can be even and divisible by 9 at once, as 18 is, so these must be two separate if statements.

Done?

That ends the chapters of Part 4. You can branch with if and switch, reason about truth with &&, ||, and !, repeat with every form of for, nest loops for grids, and pick the right loop pattern on sight. Part 4 has two mini-projects to tie it together: the Number Guessing Game and Rock-Paper-Scissors.