Índice

Tu primer proyecto

Juntando todo

A lo largo de los últimos nueve capítulos, has aprendido variables, tipos, operaciones, flujo de control, funciones, arrays, strings, maps y structs. ¡Es mucho! Ahora es momento de combinar todo en un programa real.

Vamos a construir un seguimiento de notas de estudiantes: un programa que almacena estudiantes y sus notas, calcula promedios, encuentra al mejor y peor estudiante, e imprime un informe resumen.

Paso 1: Definir los datos

Primero, definamos cómo se ve un estudiante:

struct Estudiante {
    nombre: String,
    notas: Array
}

Cada estudiante tiene un nombre y un array de notas (enteros).

Paso 2: Crear los estudiantes

fn crear_estudiante(nombre: String, notas: Array) -> Estudiante {
    return Estudiante { nombre: nombre, notas: notas }
}

Esta función auxiliar facilita la creación de estudiantes.

Paso 3: Calcular el promedio

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

Esta función suma todas las notas y divide por la cantidad. Como usamos división entera, el resultado se redondea hacia abajo.

Paso 4: Encontrar la nota más alta

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

Paso 5: Determinar la letra de calificación

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

Paso 6: Imprimir el informe de un estudiante

fn imprimir_informe(s: Estudiante) {
    let prom: int = promedio(s.notas)
    let mejor: int = nota_mas_alta(s.notas)
    let letra: String = letra_nota(prom)

    print("Estudiante: " + s.nombre)
    print("  Notas: " + int_to_string(s.notas.length()) + " tareas")
    print("  Promedio: " + int_to_string(prom))
    print("  Mejor: " + int_to_string(mejor))
    print("  Letra: " + letra)
    print("")
}

Paso 7: Encontrar al mejor estudiante

fn mejor_estudiante(estudiantes: Array) -> String {
    var mejor_nombre: String = ""
    var mejor_prom: int = 0
    var i: int = 0
    while i < estudiantes.length() {
        let s: Estudiante = estudiantes[i]
        let prom: int = promedio(s.notas)
        if prom > mejor_prom {
            mejor_prom = prom
            mejor_nombre = s.nombre
        }
        i += 1
    }
    return mejor_nombre
}

Paso 8: Estadísticas de la clase

fn promedio_clase(estudiantes: Array) -> int {
    var total: int = 0
    var i: int = 0
    while i < estudiantes.length() {
        let s: Estudiante = estudiantes[i]
        total += promedio(s.notas)
        i += 1
    }
    return total / estudiantes.length()
}

fn contar_aprobados(estudiantes: Array) -> int {
    var cuenta: int = 0
    var i: int = 0
    while i < estudiantes.length() {
        let s: Estudiante = estudiantes[i]
        if promedio(s.notas) >= 60 {
            cuenta += 1
        }
        i += 1
    }
    return cuenta
}

El programa completo

Aquí está todo junto:

struct Estudiante {
    nombre: String,
    notas: Array
}

fn crear_estudiante(nombre: String, notas: Array) -> Estudiante {
    return Estudiante { nombre: nombre, notas: notas }
}

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

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

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

fn imprimir_informe(s: Estudiante) {
    let prom: int = promedio(s.notas)
    let mejor: int = nota_mas_alta(s.notas)
    let letra: String = letra_nota(prom)
    print("Estudiante: " + s.nombre)
    print("  Promedio: " + int_to_string(prom) + " (" + letra + ")")
    print("  Mejor nota: " + int_to_string(mejor))
    print("")
}

fn mejor_estudiante(estudiantes: Array) -> String {
    var mejor_nombre: String = ""
    var mejor_prom: int = 0
    var i: int = 0
    while i < estudiantes.length() {
        let s: Estudiante = estudiantes[i]
        let prom: int = promedio(s.notas)
        if prom > mejor_prom {
            mejor_prom = prom
            mejor_nombre = s.nombre
        }
        i += 1
    }
    return mejor_nombre
}

fn promedio_clase(estudiantes: Array) -> int {
    var total: int = 0
    var i: int = 0
    while i < estudiantes.length() {
        let s: Estudiante = estudiantes[i]
        total += promedio(s.notas)
        i += 1
    }
    return total / estudiantes.length()
}

fn contar_aprobados(estudiantes: Array) -> int {
    var cuenta: int = 0
    var i: int = 0
    while i < estudiantes.length() {
        let s: Estudiante = estudiantes[i]
        if promedio(s.notas) >= 60 { cuenta += 1 }
        i += 1
    }
    return cuenta
}

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

    print("=== Informe de Notas ===")
    print("")

    var i: int = 0
    while i < estudiantes.length() {
        let s: Estudiante = estudiantes[i]
        imprimir_informe(s)
        i += 1
    }

    print("=== Resumen de la Clase ===")
    print("Estudiantes: " + int_to_string(estudiantes.length()))
    print("Promedio de la clase: " + int_to_string(promedio_clase(estudiantes)))
    print("Aprobados: " + int_to_string(contar_aprobados(estudiantes)) + "/" + int_to_string(estudiantes.length()))
    print("Mejor estudiante: " + mejor_estudiante(estudiantes))
}

Salida esperada:

=== Informe de Notas ===

Estudiante: Alice
  Promedio: 91 (A)
  Mejor nota: 95

Estudiante: Bob
  Promedio: 73 (C)
  Mejor nota: 80

Estudiante: Charlie
  Promedio: 95 (A)
  Mejor nota: 98

Estudiante: Diana
  Promedio: 59 (F)
  Mejor nota: 62

Estudiante: Eve
  Promedio: 87 (B)
  Mejor nota: 90

=== Resumen de la Clase ===
Estudiantes: 5
Promedio de la clase: 81
Aprobados: 4/5
Mejor estudiante: Charlie

Lo que construiste

Mira lo que hace este programa:

Así es como se construyen los programas reales: funciones pequeñas y enfocadas que hacen una sola cosa, combinadas para resolver un problema más grande.

Desafíos

Ahora que has completado la Parte 1, prueba estos desafíos para poner a prueba tus habilidades:

  1. Agregar nota más baja: Escribe nota_mas_baja(notas: Array) -> int e inclúyela en el informe.
  1. Distribución de calificaciones: Cuenta cuántos estudiantes obtuvieron cada letra (A, B, C, D, F) e imprime un resumen.
  1. Notas con curva: Escribe una función que sume 5 puntos a cada nota (con tope en 100) y recalcula el informe.
  1. Cuadro de honor: Imprime una lista separada de estudiantes con promedio de 90 o más.
  1. Construye tu propio proyecto: Elige algo que te interese — un registro de recetas, un marcador deportivo, una lista de reproducción de música — y constrúyelo usando todo lo que has aprendido.

¿Qué sigue?

¡Felicitaciones! Has completado la Parte 1 de El Libro de Nyx. Ahora conoces los fundamentos de la programación: variables, tipos, flujo de control, funciones, arrays, strings, maps y structs.

En la Parte 2, aprenderás a construir programas más grandes con módulos e imports, leer y escribir archivos, usar closures, enums, traits, generics, y eventualmente construir un servidor web — todo en Nyx.

Siguiente capítulo: Imports y módulos →

← Anterior: Structs Siguiente: Imports y módulos →