Start learning free

LESSON 140 OF 338 · LOOPS & GLOBAL VARIABLES

Student Grades in Go: Averaging a Slice with a Loop

Practice Read the full explanation

Given the grades of a student as an array, determine if the student has passed the class.

A Student has passed the class if the average of grades is 5 or more.

The average is defined as (grades[0] + grades[1] + ... + grades[n - 1]) / n

Example 1:

Input: grades = [4, 7, 5, 9, 8, 2]
Output: true
Explanation:
average = (4 + 7 + 5 + 9 + 8 + 2) / 6 =
= 35 / 6 = 5.833333333... >= 5

Example 2:

Input: grades = [4, 7, 5, 3, 8, 2]
Output: false
Explanation:
average = (4 + 7 + 5 + 3 + 8 + 2) / 6 =
= 29 / 6 = 4.83333.. < 5

Hints:

The problem can be broken in 3 steps:
1. Compute the sum of the array
2. Compute the average by dividing the sum by the length of the array
3. Decide the result based on the average being greater than or equal to 5
Let's start with step 1: How can we compute the sum of the array?

First of all, we should store this sum somewhere as we compute it. That 'somewhere' is a variable, let's name it sum. We have to iterate through every element of grades and add its value to sum. How can we achieve this?

With a loop! Let's use a for loop and a variable grade to iterate through the elements:
sum = 0
for each grade in grades:
	sum += grade
When the loop terminates, we know the sum. What should we do next?

We should compute average = sum / length and return average >= 5:
sum = 0
for each grade in grades:
	sum += grade
average = sum / length
return average >= 5


We have a for loop that performs exactly n iterations (n is the length of grades), thus the Time Complexity is O(n).
The only extra space we use are the variables sum, average and the iterator variable grade inside the loop, thus the Extra Space used is O(1).
STEP 1 OF 6
    Ctrl + Enter to check

    GO · LOOPS & GLOBAL VARIABLES

    Student Grades in Go, explained

    Problem overview

    The function hasPassed receives a slice of integer grades and returns a bool: true if the student's average grade is 5 or more, false otherwise. The average is the sum of all grades divided by how many there are.

    For [4, 7, 5, 9, 8, 2] the sum is 35 and there are 6 grades, so the average is about 5.83, which passes. For [4, 7, 5, 3, 8, 2] the sum is 29 and the average is about 4.83, which fails.

    Approach

    The task breaks into three small jobs: add up the grades, divide by the count, and compare the result with 5. The only repeated work is the addition, so only that part needs a loop. The loop visits every grade once and adds it to a running total.

    The division deserves a second look. In Go, dividing two int values gives an int: the fractional part is dropped. So 35 / 6 is 5 and 29 / 6 is 4, not 5.83 and 4.83. That could look like a loss of accuracy, but here it is harmless. The pass mark is the whole number 5, and for non-negative sums the truncated average is at least 5 exactly when the real average is. A real average of 4.99 truncates to 4, which fails, just as it should.

    Step by step

    1. Define the function. It takes grades, a []int, and returns a bool. Go puts the return type after the parameter list.
    2. Declare the running total. sum := 0 creates an int variable. It must exist before the loop so it keeps its value from one pass to the next.
    3. Loop over the grades with for ... range. Each pass gives an index and a value. The index isn't needed, and Go refuses variables that are declared but never used, so it goes to the blank identifier _.
    4. Add each grade to sum inside the loop.
    5. Compute the average after the loop by dividing sum by len(grades). Both operands are int, so this is integer division.
    6. Return the comparison. average >= 5 is already a bool, so there is no need for an if that returns true in one branch and false in the other.

    The solution in Go

    func hasPassed(grades []int) bool {
        sum := 0
        for _, grade := range grades {
            sum += grade
        }
        average := sum / len(grades)
        return average >= 5
    }
    

    The Go details worth a closer look:

    • Slices and len. grades is a slice, a view onto a sequence of ints. The built-in len returns its number of elements.
    • Integer division. Go divides two ints without converting to a floating-point number. If you want the exact average, convert first: float64(sum) / float64(len(grades)). Mixing an int and a float64 in one expression does not compile, so the conversions are needed on both operands.
    • Division by zero. With an empty slice, len(grades) is 0 and the division stops the program with a run-time panic, integer divide by zero. This solution assumes at least one grade; if empty input were possible, you would check len(grades) == 0 first and decide what the answer should be.
    • := declares, = assigns. sum := 0 and average := ... declare new variables and infer their types. Inside the loop, sum += grade updates the existing variable.
    • Overflow. An int is 64 bits here and silently wraps around if a sum gets too large. For grades this is not a concern.

    Complexity

    Time: O(n). The loop runs exactly once per grade, where n is the length of the slice. The division and the comparison take constant time.

    Space: O(1). The function keeps only sum, average and the loop variable, however long the slice is.

    Edge cases and common mistakes

    • Exactly 5. [5, 5, 5] has an average of exactly 5, so the result is true. The comparison must be >=, not >.
    • Just below 5. [5, 5, 4] has a real average of 4.67. The integer average is 4, so the result is false.
    • A single grade. [9] gives an average of 9 and true; [3] gives false.
    • Dividing inside the loop. Dividing each grade before adding it truncates every grade separately, so the answer can be wrong. Divide once, after the loop.
    • Forgetting that len is a function. Go slices have no .length or .size(); use len(grades).

    Testing

    • []int{4, 7, 5, 9, 8, 2} gives true.
    • []int{4, 7, 5, 3, 8, 2} gives false.
    • []int{5, 5, 4, 6} gives true.
    • []int{9} gives true.
    Keep going with GoAbout 340 step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free