Table of Contents

Your first project

Putting it all together

Over the last nine chapters, you have learned variables, types, operations, control flow, functions, arrays, strings, maps, and structs. That is a lot! Now it is time to combine everything into a real program.

We will build a student grade tracker: a program that stores students and their grades, computes averages, finds the best and worst students, and prints a summary report.

Step 1: Define the data

First, let's define what a student looks like:

struct Student {
    name: String,
    grades: Array
}

Each student has a name and an array of grades (integers).

Step 2: Create the students

fn make_student(name: String, grades: Array) -> Student {
    return Student { name: name, grades: grades }
}

This helper function makes it easy to create students.

Step 3: Calculate the average

fn average(grades: Array) -> int {
    if grades.length() == 0 {
        return 0
    }
    var total: int = 0
    var i: int = 0
    while i < grades.length() {
        total += grades[i]
        i += 1
    }
    return total / grades.length()
}

This function adds all grades and divides by the count. Since we use integer division, the result is rounded down.

Step 4: Find the highest grade

fn highest_grade(grades: Array) -> int {
    var best: int = grades[0]
    var i: int = 1
    while i < grades.length() {
        if grades[i] > best {
            best = grades[i]
        }
        i += 1
    }
    return best
}

Step 5: Determine the letter grade

fn letter_grade(avg: int) -> String {
    if avg >= 90 { return "A" }
    if avg >= 80 { return "B" }
    if avg >= 70 { return "C" }
    if avg >= 60 { return "D" }
    return "F"
}

Step 6: Print a student report

fn print_report(s: Student) {
    let avg: int = average(s.grades)
    let best: int = highest_grade(s.grades)
    let letter: String = letter_grade(avg)

    print("Student: " + s.name)
    print("  Grades: " + int_to_string(s.grades.length()) + " assignments")
    print("  Average: " + int_to_string(avg))
    print("  Best: " + int_to_string(best))
    print("  Letter: " + letter)
    print("")
}

Step 7: Find the top student

fn top_student(students: Array) -> String {
    var best_name: String = ""
    var best_avg: int = 0
    var i: int = 0
    while i < students.length() {
        let s: Student = students[i]
        let avg: int = average(s.grades)
        if avg > best_avg {
            best_avg = avg
            best_name = s.name
        }
        i += 1
    }
    return best_name
}

Step 8: Class statistics

fn class_average(students: Array) -> int {
    var total: int = 0
    var i: int = 0
    while i < students.length() {
        let s: Student = students[i]
        total += average(s.grades)
        i += 1
    }
    return total / students.length()
}

fn count_passing(students: Array) -> int {
    var count: int = 0
    var i: int = 0
    while i < students.length() {
        let s: Student = students[i]
        if average(s.grades) >= 60 {
            count += 1
        }
        i += 1
    }
    return count
}

The complete program

Here is everything put together:

struct Student {
    name: String,
    grades: Array
}

fn make_student(name: String, grades: Array) -> Student {
    return Student { name: name, grades: grades }
}

fn average(grades: Array) -> int {
    if grades.length() == 0 { return 0 }
    var total: int = 0
    var i: int = 0
    while i < grades.length() {
        total += grades[i]
        i += 1
    }
    return total / grades.length()
}

fn highest_grade(grades: Array) -> int {
    var best: int = grades[0]
    var i: int = 1
    while i < grades.length() {
        if grades[i] > best { best = grades[i] }
        i += 1
    }
    return best
}

fn letter_grade(avg: int) -> String {
    if avg >= 90 { return "A" }
    if avg >= 80 { return "B" }
    if avg >= 70 { return "C" }
    if avg >= 60 { return "D" }
    return "F"
}

fn print_report(s: Student) {
    let avg: int = average(s.grades)
    let best: int = highest_grade(s.grades)
    let letter: String = letter_grade(avg)
    print("Student: " + s.name)
    print("  Average: " + int_to_string(avg) + " (" + letter + ")")
    print("  Best score: " + int_to_string(best))
    print("")
}

fn top_student(students: Array) -> String {
    var best_name: String = ""
    var best_avg: int = 0
    var i: int = 0
    while i < students.length() {
        let s: Student = students[i]
        let avg: int = average(s.grades)
        if avg > best_avg {
            best_avg = avg
            best_name = s.name
        }
        i += 1
    }
    return best_name
}

fn class_average(students: Array) -> int {
    var total: int = 0
    var i: int = 0
    while i < students.length() {
        let s: Student = students[i]
        total += average(s.grades)
        i += 1
    }
    return total / students.length()
}

fn count_passing(students: Array) -> int {
    var count: int = 0
    var i: int = 0
    while i < students.length() {
        let s: Student = students[i]
        if average(s.grades) >= 60 { count += 1 }
        i += 1
    }
    return count
}

fn main() {
    let students: Array = [
        make_student("Alice",   [92, 88, 95, 90]),
        make_student("Bob",     [78, 65, 72, 80]),
        make_student("Charlie", [95, 98, 92, 97]),
        make_student("Diana",   [55, 62, 58, 61]),
        make_student("Eve",     [88, 85, 90, 87])
    ]

    print("=== Student Grade Report ===")
    print("")

    var i: int = 0
    while i < students.length() {
        let s: Student = students[i]
        print_report(s)
        i += 1
    }

    print("=== Class Summary ===")
    print("Students: " + int_to_string(students.length()))
    print("Class average: " + int_to_string(class_average(students)))
    print("Passing: " + int_to_string(count_passing(students)) + "/" + int_to_string(students.length()))
    print("Top student: " + top_student(students))
}

Expected output:

=== Student Grade Report ===

Student: Alice
  Average: 91 (A)
  Best score: 95

Student: Bob
  Average: 73 (C)
  Best score: 80

Student: Charlie
  Average: 95 (A)
  Best score: 98

Student: Diana
  Average: 59 (F)
  Best score: 62

Student: Eve
  Average: 87 (B)
  Best score: 90

=== Class Summary ===
Students: 5
Class average: 81
Passing: 4/5
Top student: Charlie

What you built

Look at what this program does:

This is how real programs are built: small, focused functions that each do one thing, combined together to solve a bigger problem.

Challenges

Now that you have completed Part 1, try these challenges to test your skills:

  1. Add a lowest grade function: Write lowest_grade(grades: Array) -> int and include it in the report.
  1. Grade distribution: Count how many students got each letter grade (A, B, C, D, F) and print a summary.
  1. Curved grades: Write a function that adds 5 points to every grade (capped at 100) and recompute the report.
  1. Honor roll: Print a separate list of students with an average of 90 or above.
  1. Build your own project: Pick something you care about — a recipe tracker, a sports scoreboard, a music playlist — and build it using everything you have learned.

What's next?

Congratulations! You have completed Part 1 of The Nyx Book. You now know the fundamentals of programming: variables, types, control flow, functions, arrays, strings, maps, and structs.

In Part 2, you will learn how to build larger programs with modules and imports, read and write files, use closures, enums, traits, generics, and eventually build a web server — all in Nyx.

Next chapter: Imports and modules →

← Previous: Structs Next: Imports and modules →