16. if, else and switch — Homework solutions

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

Problem 1 — Even or odd

Problem. Read a number; print even or odd.

How to think about it. n % 2 is 0 for even numbers. Anything else is odd. One if and one else.

Worked solution.

package main

import (
    "bufio"
    "fmt"
    "os"
    "strconv"
    "strings"
)

func main() {
    reader := bufio.NewReader(os.Stdin)

    fmt.Print("Enter a whole number: ")
    text, _ := reader.ReadString('\n')
    n, _ := strconv.Atoi(strings.TrimSpace(text))

    if n%2 == 0 {
        fmt.Println("even")
    } else {
        fmt.Println("odd")
    }
}

Output, typing 7:

Enter a whole number: 7
odd

Common mistakes.

  • Writing if n%2 = 0 {. A single = is assignment, and Go stops with syntax error: cannot use assignment (n % 2) = 0 as value.
  • Testing n%2 == 1 for odd. It works for positive numbers only, because -3 % 2 gives -1. Testing against 0 is correct for every whole number.
  • Forgetting to convert. % needs an int, so the text from ReadString has to go through strconv.Atoi first. Typing abc gives 0, as Chapter 15 warned, and the program prints even.

Problem 2 — Level gate

Problem. Different messages depending on which of two requirements the player fails.

How to think about it. Two bools give four combinations, and only one of them is good. Spell each out with else if:

  • both ok → enter
  • both wrong → "Level too low and missing the key."
  • level low, key ok → "Level too low."
  • level ok, key missing → "Missing the key."

Branch order matters: handle the most specific failure first.

Worked solution.

package main

import "fmt"

func main() {
    level := 12
    hasKey := true

    if level >= 10 && hasKey {
        fmt.Println("You can enter the dungeon.")
    } else if level < 10 && !hasKey {
        fmt.Println("Level too low and missing the key.")
    } else if level < 10 {
        fmt.Println("Level too low.")
    } else {
        fmt.Println("Missing the key.")
    }
}

Output:

You can enter the dungeon.

The combined failure is checked before the single ones. If else if level < 10 came first, it would swallow the combined case, and that message would never show.

Common mistakes.

  • Writing the words and or or. Go uses && and ||, and if level >= 10 and hasKey { stops with syntax error: unexpected and, expected {.
  • Forgetting that !hasKey means the key is missing. Say it out loud: "not has key".

Problem 3 — Grade letter

Problem. Standard A/B/C/D/F based on cutoffs.

How to think about it. Each case checks the highest cutoff not yet caught. In a switch, once a case matches, the rest are skipped.

Worked solution.

package main

import (
    "bufio"
    "fmt"
    "os"
    "strconv"
    "strings"
)

func main() {
    reader := bufio.NewReader(os.Stdin)

    fmt.Print("Score (0-100): ")
    text, _ := reader.ReadString('\n')
    score, _ := strconv.Atoi(strings.TrimSpace(text))

    switch {
    case score >= 90:
        fmt.Println("Grade: A")
    case score >= 80:
        fmt.Println("Grade: B")
    case score >= 70:
        fmt.Println("Grade: C")
    case score >= 60:
        fmt.Println("Grade: D")
    default:
        fmt.Println("Grade: F")
    }
}

Output, typing 85:

Score (0-100): 85
Grade: B

Common mistakes.

  • Listing the conditions from low to high. Putting score >= 60 first catches every passing score, including 95, and gives them all a D.
  • Using > instead of >=. A score of exactly 90 should be an A, not a B.
  • Writing switch score { with conditions in the cases. Conditions need a switch with no value.

Challenge — Largest of three

Problem. Three numbers, only if and comparisons. Print the largest.

How to think about it. Compare them pair by pair. a >= b and a >= c means a is the largest, or tied for it. >= (not >) handles ties: if a equals b and both beat c, the first branch wins and prints a.

Worked solution.

package main

import "fmt"

func main() {
    a := 7
    b := 12
    c := 12

    if a >= b && a >= c {
        fmt.Println(a)
    } else if b >= c {
        fmt.Println(b)
    } else {
        fmt.Println(c)
    }
}

Output:

12

Trace through a := 7, b := 12, c := 12:

  • a >= b? 7 >= 12 is false. First branch skipped.
  • b >= c? 12 >= 12 is true. Prints 12.

For a := 12, b := 12, c := 5:

  • a >= b? 12 >= 12 is true.
  • a >= c? 12 >= 5 is true.
  • Both true, so print a, 12. Done.

Common mistakes.

  • Using > instead of >=. With a := 12, b := 12, c := 5, the first branch is now false. The right value still prints, but only because a later branch happens to catch it, which makes the logic harder to follow.

Done?

The next chapter, Boolean logic in depth, digs into what &&, ||, and ! actually do, and into the rule that only a bool can go in an if. After that come loops, the other way to make a program do something different each run.