- Rust 100%
| .forgejo/workflows | ||
| src | ||
| tests | ||
| .gitignore | ||
| .woodpecker.yml | ||
| Cargo.lock | ||
| Cargo.toml | ||
| LICENSE | ||
| README.md | ||
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-1para 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
- Implementar
obter_coordenada: Retorne o valor x, y ou z de uma tupla de coordenadas baseado no índice (0, 1, 2). RetorneNonese o índice for inválido. - Implementar
calcular_media_temperaturas: Calcule a média aritmética de 5 leituras de temperatura armazenadas em um array. - Implementar
formatar_leitura_sensor: Receba uma tupla com 4 valores u8 e retorne uma string formatada com todos os valores. - Implementar
trocar_valores: Troque dois elementos em um array de 3 posições. Retornetruese a troca for bem-sucedida,falsese os índices forem inválidos. - 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
matchou uma sequência deif - 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 retornarSome(valor)ouNonequando o índice for inválido