Desafio Rust

Processador de formas com if let e match

Enunciado

Crie um enum Forma com as variantes Circulo(f64), Retangulo { largura: f64, altura: f64 } e Triangulo { base: f64, altura: f64 }. Implemente area(&self) -> f64 usando match. No main, crie um vetor de formas, calcule a área total e, usando if let, verifique se alguma forma é um círculo e imprima seu raio. Exiba a área total formatada com duas casas decimais.

Requisitos

  • O enum Forma deve ter as três variantes com os dados especificados.
  • A função area deve usar match exaustivo e retornar f64.
  • O main deve criar um vetor com pelo menos um círculo, um retângulo e um triângulo.
  • Calcular e imprimir a área total com duas casas decimais.
  • Usar if let para encontrar e imprimir o raio do primeiro círculo do vetor.

Código inicial

enum Forma {
    Circulo(f64),
    Retangulo { largura: f64, altura: f64 },
    Triangulo { base: f64, altura: f64 },
}

impl Forma {
    fn area(&self) -> f64 {
        // Complete com match
        todo!()
    }
}

fn main() {
    let formas = vec![
        Forma::Circulo(1.0),
        Forma::Retangulo { largura: 2.0, altura: 3.0 },
        Forma::Triangulo { base: 4.0, altura: 5.0 },
    ];

    // Calcule a área total
    // Use if let para achar um círculo e imprimir seu raio
}

Saída esperada

Área total: 19.14
Raio do círculo: 1
Ver dica

Para a área do círculo, use std::f64::consts::PI. Para o if let, itere sobre &formas e use if let Forma::Circulo(raio) = forma. Lembre-se de que raio será uma referência (&f64), então use *raio para obter o valor.

Mostrar solução
enum Forma {
    Circulo(f64),
    Retangulo { largura: f64, altura: f64 },
    Triangulo { base: f64, altura: f64 },
}

impl Forma {
    fn area(&self) -> f64 {
        match self {
            Forma::Circulo(raio) => std::f64::consts::PI * raio * raio,
            Forma::Retangulo { largura, altura } => largura * altura,
            Forma::Triangulo { base, altura } => (base * altura) / 2.0,
        }
    }
}

fn main() {
    let formas = vec![
        Forma::Circulo(1.0),
        Forma::Retangulo { largura: 2.0, altura: 3.0 },
        Forma::Triangulo { base: 4.0, altura: 5.0 },
    ];

    // Calcula a área total
    let total: f64 = formas.iter().map(|f| f.area()).sum();
    println!("Área total: {:.2}", total);

    // Usa if let para achar o primeiro círculo e imprimir seu raio
    for forma in &formas {
        if let Forma::Circulo(raio) = forma {
            println!("Raio do círculo: {}", raio);
            break;
        }
    }
}

Passo a passo

  1. Definimos o enum Forma com três variantes, cada uma com os dados necessários.
  2. Implementamos o método area usando match self para calcular a área de cada forma.
  3. No braço Circulo, usamos std::f64::consts::PI e o raio extraído.
  4. No braço Retangulo, desestruturamos largura e altura e multiplicamos.
  5. No braço Triangulo, desestruturamos base e altura e aplicamos a fórmula (base * altura) / 2.0.
  6. No main, criamos um vetor de formas.
  7. Calculamos a área total com iter().map(|f| f.area()).sum().
  8. Imprimimos a área total com duas casas decimais.
  9. Iteramos sobre as formas e usamos if let Forma::Circulo(raio) = forma para encontrar o primeiro círculo, imprimimos seu raio e saímos do loop com break.

Por que funciona

O match dentro de area cobre todas as variantes, retornando o cálculo correto para cada uma. O método recebe &self, então os padrões desestruturam referências automaticamente. O if let permite verificar apenas a variante Circulo sem precisar de um match completo, e o break garante que apenas o primeiro círculo seja impresso.

Erros comuns

  • Esquecer de tratar uma variante no match: erro de compilação por não exaustividade.
  • Tentar usar raio como f64 diretamente no if let: como forma é &Forma, raio é &f64; é preciso desreferenciar com *raio se for usar em cálculos, mas na impressão println! aceita referência.
  • Não importar std::f64::consts::PI: erro de nome não encontrado. Use o caminho completo ou use std::f64::consts::PI;.
  • Esquecer o break no if let: imprimiria todos os círculos, não apenas o primeiro.

Outra forma de resolver

Usar formas.iter().find_map(|f| if let Forma::Circulo(r) = f { Some(*r) } else { None }) para obter o raio do primeiro círculo de forma mais funcional. Preferível quando se quer evitar loops explícitos.

Saída esperada

Área total: 19.14
Raio do círculo: 1