No description
Find a file
Jonatas Oliveira bb7807f139
Some checks failed
Rust CI / clippy (push) Has been cancelled
Rust CI / fmt (push) Has been cancelled
Rust CI / audit (push) Has been cancelled
feat: inicital commit
2026-07-29 11:09:38 +02:00
.forgejo/workflows feat: inicital commit 2026-07-29 11:09:38 +02:00
src feat: inicital commit 2026-07-29 11:09:38 +02:00
tests feat: inicital commit 2026-07-29 11:09:38 +02:00
.gitignore Initial commit 2026-07-29 09:08:50 +00:00
.woodpecker.yml feat: inicital commit 2026-07-29 11:09:38 +02:00
Cargo.lock feat: inicital commit 2026-07-29 11:09:38 +02:00
Cargo.toml feat: inicital commit 2026-07-29 11:09:38 +02:00
LICENSE Initial commit 2026-07-29 09:08:50 +00:00
README.md feat: inicital commit 2026-07-29 11:09:38 +02:00

Lição 3: Sistemas Compostos

Narrativa

Piloto, os sistemas do seu mecha raramente operam de forma isolada. Os sensores de navegação fornecem coordenadas tridimensionais — três valores que trabalham juntos como um único ponto no espaço. Os sensores de ambiente retornam múltiplas leituras simultâneas: temperatura, umidade, pressão, radiação. Estes são sistemas compostos: coleções de dados que formam uma unidade coerente.

Na Academia Æther, você aprenderá duas ferramentas fundamentais para lidar com sistemas compostos. Arrays são usados quando você tem múltiplos valores do mesmo tipo — como as 5 leituras de temperatura do sensor térmico. Tuplas são usadas quando você precisa combinar valores de tipos diferentes — como uma coordenada (x, y, z) ou uma identificação de unidade (código, nome, nível). Dominar estas estruturas é essencial para interpretar os dados complexos que seu mecha constantemente processa.

Conceito

Rust oferece duas estruturas fundamentais para agrupar dados: arrays e tuplas.

Arrays ([T; N]): Coleções de tamanho fixo onde todos os elementos são do mesmo tipo. Arrays residem na stack, são extremamente eficientes e seu tamanho faz parte do tipo:

let temperaturas: [f64; 5] = [20.5, 21.0, 20.8, 21.2, 20.9];
let primeira = temperaturas[0]; // Acesso por índice

Tuplas ((T1, T2, T3)): Coleções de tamanho fixo que podem conter tipos diferentes. Úteis para retornar múltiplos valores ou agrupar dados relacionados:

let coordenada: (i32, i32, i32) = (100, 200, 50);
let (x, y, z) = coordenada; // Desestruturação
let x = coordenada.0; // Acesso por índice posicional

A diferença crucial: arrays são homogêneos (mesmo tipo), tuplas são heterogêneas (tipos podem variar). Arrays usam colchetes [], tuplas usam parênteses ().

Requisitos

  • Entrada: Arrays fixos de valores numéricos e tuplas de dados heterogêneos
  • Processamento: Acessar elementos por índice, calcular métricas sobre arrays, desestruturar tuplas, validar limites
  • Saída: Valores individuais de tuplas, médias calculadas, strings formatadas, operações seguras com verificação de limites

Design de Dados

Esta lição trabalha com estruturas compostas em Rust — arrays para coleções homogêneas e tuplas para agrupamentos heterogêneos:

// Funções para manipulação de sistemas compostos
pub fn obter_coordenada(coordenadas: &(i32, i32, i32), indice: usize) -> Option<i32>;
pub fn calcular_media_temperaturas(temps: &[f64; 5]) -> f64;
pub fn formatar_leitura_sensor(dados: &(u8, u8, u8, u8)) -> String;
pub fn trocar_valores(array: &mut [i32; 3], idx1: usize, idx2: usize) -> bool;
pub fn extrair_tipo_unidade(unidade: &(char, &str, i32)) -> String;

Arrays têm tamanho conhecido em tempo de compilação e residem na stack. Tuplas permitem combinar tipos diferentes. Referências (&) são usadas para evitar cópias desnecessárias e permitir mutação controlada.

Diagrama Conceitual

flowchart TD
    A[Dados Compostos] --> B{Tipo Homogêneo?}
    B -->|Sim| C[Array]
    B -->|Não| D[Tupla]
    C --> E[Acesso por Índice]
    C --> F[Iteração]
    D --> G[Desestruturação]
    D --> H[Acesso Posicional]
    E --> I[Processamento]
    F --> I
    G --> I
    H --> I

Funções e Módulos

//! Lição 3: Sistemas Compostos
//!
//! Trabalhando com arrays e tuplas para gerenciar dados compostos.

/// Obtém uma coordenada pelo índice (0=x, 1=y, 2=z)
pub fn obter_coordenada(coordenadas: &(i32, i32, i32), indice: usize) -> Option<i32>;

/// Calcula a média de 5 leituras de temperatura
pub fn calcular_media_temperaturas(temps: &[f64; 5]) -> f64;

/// Formata uma leitura de sensor em string
pub fn formatar_leitura_sensor(dados: &(u8, u8, u8, u8)) -> String;

/// Troca dois valores em um array de 3 posições
pub fn trocar_valores(array: &mut [i32; 3], idx1: usize, idx2: usize) -> bool;

/// Extrai o tipo de unidade formatado de uma tupla
pub fn extrair_tipo_unidade(unidade: &(char, &str, i32)) -> String;

Exemplo do Conceito

// ARRAYS: Coleções homogêneas de tamanho fixo
let leituras: [f64; 3] = [20.5, 21.0, 20.8];
let primeira = leituras[0]; // 20.5

// TUPLAS: Agrupamentos heterogêneos
let sensor: (u8, &str, bool) = (42, "térmico", true);
let (id, nome, ativo) = sensor; // Desestruturação
let id = sensor.0; // Acesso por posição

// ARRAYS multi-dimensionais (array de arrays)
let matriz: [[i32; 2]; 3] = [
    [1, 2],
    [3, 4],
    [5, 6],
];

// TUPLAS como retorno de múltiplos valores
fn dividir(dividendo: i32, divisor: i32) -> (i32, i32) {
    (dividendo / divisor, dividendo % divisor)
}
let (quociente, resto) = dividir(17, 5); // (3, 2)

Explicação:

  • Arrays usam índices 0..N-1 para acesso; acesso fora dos limites causa pânico
  • Tuplas podem ser desestruturadas em variáveis individuais ou acessadas por .0, .1, etc.
  • Arrays têm tamanho fixo conhecido em tempo de compilação; não podem crescer ou encolher
  • Referências (&[T; N]) permitem trabalhar com arrays sem transferir ownership

Missão

  1. Implementar obter_coordenada: Retorne o valor x, y ou z de uma tupla de coordenadas baseado no índice (0, 1, 2). Retorne None se o índice for inválido.
  2. Implementar calcular_media_temperaturas: Calcule a média aritmética de 5 leituras de temperatura armazenadas em um array.
  3. Implementar formatar_leitura_sensor: Receba uma tupla com 4 valores u8 e retorne uma string formatada com todos os valores.
  4. Implementar trocar_valores: Troque dois elementos em um array de 3 posições. Retorne true se a troca for bem-sucedida, false se os índices forem inválidos.
  5. Implementar extrair_tipo_unidade: Receba uma tupla contendo (código, nome, nível) e retorne uma string formatada descrevendo a unidade.

Diagrama de Fluxo da Missão

flowchart TD
    A[Tarefa: Sistemas Compostos] --> B[Implementar obter_coordenada]
    B --> C[Implementar calcular_media_temperaturas]
    C --> D[Implementar formatar_leitura_sensor]
    D --> E[Implementar trocar_valores]
    E --> F[Implementar extrair_tipo_unidade]
    F --> G[Testes verificam]
    G --> H{Clippy limpo?}
    H -->|Sim| I[Concluído]
    H -->|Não| J[Corrigir warnings] --> G

Como Executar

# Executar testes
cargo test

# Verificar lint
cargo clippy -- -D warnings

# Formatar código
cargo fmt --check

Dicas

  • Arrays têm tamanho fixo; use .len() para obter o tamanho (disponível em tempo de compilação)
  • Para acessar elementos de tupla por índice dinâmico, use match ou uma sequência de if
  • A média de floats requer soma dos elementos e divisão pelo número de elementos
  • Para trocar valores em um array mutável, use a técnica de swap com variável temporária
  • format!("{}", valor) é útil para criar strings formatadas a partir de dados
  • Lembre-se de verificar limites antes de acessar arrays — Rust não permite acesso inseguro
  • Use Option<i32> para retornar Some(valor) ou None quando o índice for inválido