🎓 A1Learner
🔍
0 of 55 lessons completed

Zig Project: Grade Tracker

A grade tracker is a program that turns a list of scores into a summary. This project reports the average, the highest and lowest scores, the pass count, and a letter band.

An average function over a slice

The function adds every score in the slice, then divides by the count. The five scores sum to 361, and 361 divided by 5 is 72.2.

const std = @import("std");

fn average(scores: []const i32) f64 {
    var sum: i32 = 0;
    for (scores) |s| {
        sum += s;
    }
    const sum_f: f64 = @floatFromInt(sum);
    const count_f: f64 = @floatFromInt(scores.len);
    return sum_f / count_f;
}

pub fn main() !void {
    const out = std.io.getStdOut().writer();
    const scores = [_]i32{ 72, 85, 49, 91, 64 };
    const avg = average(&scores);
    try out.print("Average: {d:.1}\n", .{avg});
}

Highest, lowest, and pass count in one loop

One loop tracks the largest and smallest scores seen so far. It also counts each score of 60 or more as a pass.

const std = @import("std");

pub fn main() !void {
    const out = std.io.getStdOut().writer();
    const scores = [_]i32{ 72, 85, 49, 91, 64 };
    var highest = scores[0];
    var lowest = scores[0];
    var passes: i32 = 0;
    for (scores) |s| {
        if (s > highest) {
            highest = s;
        }
        if (s < lowest) {
            lowest = s;
        }
        if (s >= 60) {
            passes += 1;
        }
    }
    try out.print("Highest: {d}\n", .{highest});
    try out.print("Lowest: {d}\n", .{lowest});
    try out.print("Passes: {d}\n", .{passes});
}

A switch turns a score into a band letter

The band function matches the score against ranges, highest first. A score of 91 lands in the top range, and 49 falls through to the else prong.

const std = @import("std");

fn band(score: i32) u8 {
    return switch (score) {
        90...100 => 'A',
        80...89 => 'B',
        70...79 => 'C',
        60...69 => 'D',
        else => 'F',
    };
}

pub fn main() !void {
    const out = std.io.getStdOut().writer();
    try out.print("91 earns {c}\n", .{band(91)});
    try out.print("49 earns {c}\n", .{band(49)});
}

Example

const std = @import("std");

fn average(scores: []const i32) f64 {
    var sum: i32 = 0;
    for (scores) |s| {
        sum += s;
    }
    const sum_f: f64 = @floatFromInt(sum);
    const count_f: f64 = @floatFromInt(scores.len);
    return sum_f / count_f;
}

fn band(score: i32) u8 {
    return switch (score) {
        90...100 => 'A',
        80...89 => 'B',
        70...79 => 'C',
        60...69 => 'D',
        else => 'F',
    };
}

pub fn main() !void {
    const out = std.io.getStdOut().writer();
    var scores = [_]i32{ 72, 85, 49, 91, 64 };
    std.mem.sort(i32, &scores, {}, comptime std.sort.asc(i32));
    try out.print("Scores: {any}\n", .{scores});
    const avg = average(&scores);
    try out.print("Average: {d:.1}\n", .{avg});
    try out.print("Highest: {d}\n", .{scores[scores.len - 1]});
    try out.print("Lowest: {d}\n", .{scores[0]});
    var passes: i32 = 0;
    for (scores) |s| {
        if (s >= 60) {
            passes += 1;
        }
    }
    try out.print("Passes: {d} of {d}\n", .{ passes, scores.len });
    const avg_score: i32 = @intFromFloat(avg);
    try out.print("Class band: {c}\n", .{band(avg_score)});
}

Key points

  • Score list: a fixed array holds every score for one class.
  • Average: the sum of the scores divided by how many scores there are.
  • Pass: a score of 60 or more counts as a pass.
  • Band: a switch turns a score range into a letter such as A or C.
  • Sort: std.mem.sort orders the scores, so the first is the lowest and the last is the highest.

In this example, the program sorts the five scores into ascending order and prints them. The average function returns 72.2, printed with one decimal place. The sorted ends give the lowest score, 49, and the highest, 91, and a counting loop finds 4 passes out of 5. The average is converted back to an integer so the band function can grade the class with a C.

Note

the average needs float division, so the integer sum is converted with @floatFromInt before dividing.

Try it Yourself

Edit the code, then press Run.

Running is simulated

Exercise

After the scores are sorted in ascending order, where is the highest score?