Track
/
Rust
Rust
/
Esercizi
/
Gioco embedded a basso consumo
Gioco embedded a basso consumo

Gioco embedded a basso consumo

Esercizio di apprendimento

Introduzione

Le tuple sono un modo leggero per raggruppare un insieme fisso di tipi di dati arbitrari. Una tupla non ha un nome particolare; dare un nome a una struttura dati la trasforma in una struct. I campi di una tupla non hanno nomi; vi si accede tramite destrutturazione o per posizione.

Sintassi

Creazione

Le tuple vengono sempre create con un'espressione tupla:

// 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");

Le tuple possono avere un numero arbitrario di elementi.

Accesso tramite destrutturazione

È possibile accedere agli elementi di una tupla tramite destrutturazione. Questo significa semplicemente assegnare nomi di variabile ai singoli elementi della tupla, consumandola.

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

Accesso per posizione

È anche possibile accedere agli elementi di una tupla tramite un indice posizionale numerico. L'indicizzazione, come sempre, inizia da 0.

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

Struct tupla

Ti verrà anche chiesto di lavorare con le struct tupla. Come le struct normali, sono tipi con nome; a differenza delle struct normali, hanno campi anonimi. La loro sintassi è molto simile alla normale sintassi delle tuple. È lecito usare sia la destrutturazione sia l'accesso per posizione.

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);

Visibilità dei campi

Tutti i campi delle tuple anonime sono sempre pubblici. Tuttavia, i campi delle struct tupla hanno una visibilità individuale che, per impostazione predefinita, è privata, proprio come i campi delle struct standard. Puoi rendere pubblici i campi con il modificatore pub, proprio come in una struct standard.

// 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); }

Istruzioni

Stai lavorando a un gioco destinato a un sistema embedded a basso consumo e devi scrivere alcune funzioni di utilità che verranno usate da altre parti del gioco.

1. Calcolare il quoziente e il resto di una divisione

Il quoziente è l'output di una divisione.

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

Esempio:

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

2. Scegliere gli elementi in posizione pari da un iteratore

A detta del tuo capo, servirà ad abilitare un'ottimizzazione del buffer dello schermo.

Gli iteratori sono elementi che espongono i metodi definiti dal trait Iterator. Quella documentazione è piuttosto ampia, perché offrono molti metodi; ecco le proprietà più rilevanti:

  • Un iteratore è un flusso di elementi di lunghezza arbitraria
  • Hanno un metodo enumerate che restituisce una tupla (i, val) per ogni valore
  • Hanno un metodo filter che usa una chiusura per determinare se produrre un elemento dell'iteratore
  • Hanno un metodo map che usa una chiusura per modificare gli elementi dell'iteratore

Poiché la tua funzione può essere eseguita su qualsiasi tipo di iteratore, usa impl per indicare che si tratta di un'istanza di un trait invece che di un semplice elemento. Allo stesso modo, la sintassi <Item=T> significa semplicemente che non importa che tipo di elemento produca l'iteratore; la tua funzione può produrre gli elementi pari di qualsiasi iteratore.

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

Esempi:

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. Calcolare la distanza di Manhattan di una posizione dall'origine

Per comodità di mappatura, hai una struct tupla Position:

struct Position(i16, i16);

Devi implementare un metodo manhattan su Position che restituisce la distanza di Manhattan di quella posizione dall'origine (Position(0, 0)).

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

Esempio:

assert_eq!(Position(3, 4).manhattan(), 7);
Modifica tramite GitHub Il link si apre in una nuova finestra o scheda
Rust Exercism

Vuoi iniziare Gioco embedded a basso consumo?

Iscriviti a Exercism per imparare e padroneggiare Rust con 99 esercizi e il mentoring di persone reali, tutto gratis.