Percursos
/
Rust
Rust
/
Exercícios
/
Jogo embutido de baixo consumo
Jogo embutido de baixo consumo

Jogo embutido de baixo consumo

Exercício de aprendizagem

Introdução

Os tuplos são uma forma leve de agrupar um conjunto fixo de dados de tipos arbitrários. Um tuplo não tem um nome próprio; dar um nome a uma estrutura de dados transforma-a num struct. Os campos de um tuplo não têm nome; acede-se a eles por desestruturação ou por posição.

Sintaxe

Criação

Os tuplos são sempre criados com uma expressão de tuplo:

// pointless but legal
let unit = ();
// single element
let single_element = ("note the comma",);
// two element
let two_element = (123, "elements can be of differing types");

Os tuplos podem ter um número arbitrário de elementos.

Acesso por desestruturação

É possível aceder aos elementos de um tuplo por desestruturação. Isto significa apenas atribuir nomes de variáveis aos elementos individuais do tuplo, consumindo-o.

let (elem1, _elem2) = two_element;
assert_eq!(elem1, 123);

Acesso por posição

Também é possível aceder aos elementos de um tuplo através de um índice posicional numérico. A indexação, como sempre, começa no 0.

let notation = single_element.0;
assert_eq!(notation, "note the comma");

Structs de tuplo

Também te vão pedir para trabalhar com structs de tuplo. Tal como as structs normais, estes são tipos com nome; ao contrário das structs normais, têm campos anónimos. A sua sintaxe é muito semelhante à sintaxe normal de tuplos. É possível usar tanto a desestruturação como o acesso posicional.

struct TupleStruct(u8, i32);
let my_tuple_struct = TupleStruct(123, -321);
let neg = my_tuple_struct.1;
let TupleStruct(byte, _) = my_tuple_struct;
assert_eq!(neg, -321);
assert_eq!(byte, 123);

Visibilidade dos campos

Todos os campos dos tuplos anónimos são sempre públicos. No entanto, os campos das structs de tuplo têm visibilidade individual, que por defeito é privada, tal como os campos das structs normais. Podes tornar os campos públicos com o modificador pub, tal como numa struct normal.

// fails due to private fields
mod tuple { pub struct TupleStruct(u8, i32); }
fn main() { let _my_tuple_struct = tuple::TupleStruct(123, -321); }
// succeeds: fields are public
mod tuple { pub struct TupleStruct(pub u8, pub i32); }
fn main() { let _my_tuple_struct = tuple::TupleStruct(123, -321); }

Instruções

Estás a trabalhar num jogo para um sistema embutido de baixo consumo e precisas de escrever várias funções utilitárias que vão ser usadas por outras partes do jogo.

1. Calcula o quociente e o resto de uma divisão

O quociente é o resultado de uma divisão.

fn divmod(dividend: i16, divisor: i16) -> (i16, i16)

Exemplo:

assert_eq!(divmod(10, 3), (3, 1));

2. Escolhe itens em posições pares de um iterador

Isto vai ajudar a ativar uma otimização do buffer do ecrã, promete o teu chefe.

Os iteradores são itens que expõem os métodos definidos pela trait Iterator. Essa documentação é bastante extensa, porque oferecem muitos métodos; aqui ficam as propriedades mais relevantes:

  • Um iterador é um fluxo de itens de comprimento arbitrário
  • Têm um método enumerate que devolve um tuplo (i, val) para cada valor
  • Têm um método filter que usa uma closure para determinar se deve produzir um elemento do iterador
  • Têm um método map que usa uma closure para modificar elementos do iterador

Como a tua função pode correr sobre qualquer tipo de iterador, usa impl para indicar que se trata de uma instância de uma trait e não de um item simples. Da mesma forma, a sintaxe <Item=T> significa apenas que não importa que tipo de item o iterador produz; a tua função pode produzir os elementos pares de qualquer iterador.

fn evens<T>(iter: impl Iterator<Item=T>) -> impl Iterator<Item=T>

Exemplos:

let mut even_ints = evens(0_u8..);
assert_eq!(even_ints.next(), Some(0));
assert_eq!(even_ints.next(), Some(2));
assert_eq!(even_ints.next(), Some(4));
assert_eq!(even_ints.next(), Some(6));
let mut evens_from_odds = evens(1_i16..);
assert_eq!(evens_from_odds.next(), Some(1));
assert_eq!(evens_from_odds.next(), Some(3));
assert_eq!(evens_from_odds.next(), Some(5));
assert_eq!(evens_from_odds.next(), Some(7));

3. Calcula a distância de Manhattan de uma posição à origem

Para facilitar o mapeamento, tens uma tuple struct Position:

struct Position(i16, i16);

Precisas de implementar um método manhattan em Position que devolve a distância de Manhattan dessa posição à origem (Position(0, 0)).

impl Position {
    fn manhattan(&self) -> i16
}

Exemplo:

assert_eq!(Position(3, 4).manhattan(), 7);
Editar via GitHub A ligação abre numa nova janela ou separador
Rust Exercism

Estás pronto para começar Jogo embutido de baixo consumo?

Inscreve-te no Exercism para aprenderes e dominares Rust com 99 exercícios, e mentoria humana real, tudo grátis.