Треки
/
Rust
Rust
/
Вправи
/
Гра на малопотужному вбудованому пристрої
Гра на малопотужному вбудованому пристрої

Гра на малопотужному вбудованому пристрої

Навчальна вправа

Вступ

Кортежі - це легкий спосіб згрупувати докупи фіксований набір даних довільних типів. Кортеж не має конкретного імені; коли ми даємо структурі даних імʼя, вона стає struct. Поля кортежу не мають імен; до них звертаються через деструктуризацію або за позицією.

Синтаксис

Створення

Кортежі завжди створюють за допомогою виразу кортежу:

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

Кортежі можуть містити довільну кількість елементів.

Доступ через деструктуризацію

До елементів кортежу можна дістатися через деструктуризацію. Це просто означає, що ми даємо імена змінних окремим елементам кортежу, поглинаючи його.

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

Доступ за позицією

Також до елементів кортежу можна дістатися за числовим індексом позиції. Індексація, як завжди, починається з 0.

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

Кортежні структури

Також нам доведеться попрацювати з кортежними структурами. Як і звичайні структури, це іменовані типи; на відміну від звичайних структур, вони мають анонімні поля. Їхній синтаксис дуже схожий на синтаксис звичайних кортежів. Можна використовувати і деструктуризацію, і доступ за позицією.

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

Видимість полів

Усі поля анонімних кортежів завжди публічні. Проте поля кортежних структур мають власну видимість, яка типово є приватною, так само як поля звичайних структур. Ми можемо зробити поля публічними за допомогою модифікатора pub, так само як у звичайній структурі.

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

Вказівки

Ми працюємо над грою для малопотужної вбудованої системи, і нам потрібно написати кілька допоміжних функцій, які будуть використовувати інші частини гри.

1. Обчисліть частку й остачу від ділення

Частку отримуємо в результаті ділення.

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

Приклад:

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

2. Виберіть елементи на парних позиціях з ітератора

Це допоможе увімкнути оптимізацію буфера екрана, обіцяє керівник.

Ітератори - це обʼєкти, які надають методи, визначені трейтом Iterator. Ця документація досить обширна, бо ітератори надають багато методів; ось найважливіші властивості:

  • Ітератор - це потік елементів довільної довжини
  • Вони мають метод enumerate, який повертає кортеж (i, val) для кожного значення
  • Вони мають метод filter, який використовує замикання, щоб визначити, чи варто видавати елемент ітератора
  • Вони мають метод map, який використовує замикання, щоб змінювати елементи ітератора

Оскільки функція може працювати з будь-яким ітератором, у ній використовується impl, щоб показати, що це екземпляр трейту, а не простий елемент. Так само синтаксис <Item=T> просто означає, що не має значення, які саме елементи породжує ітератор; функція може повертати парні елементи будь-якого ітератора.

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

Приклади:

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. Обчисліть мангеттенську відстань позиції від початку координат

Для зручності роботи з координатами є кортежна структура Position:

struct Position(i16, i16);

Потрібно реалізувати метод manhattan у Position, який повертає манхеттенську відстань цієї позиції від початку координат (Position(0, 0)).

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

Приклад:

assert_eq!(Position(3, 4).manhattan(), 7);
Редагувати через GitHub Посилання відкривається в новому вікні або вкладці
Rust Exercism

Час розпочати Гра на малопотужному вбудованому пристрої?

Зареєструйтеся на Exercism, щоб вивчати й опановувати Rust, а також 99 вправ та справжнє наставництво від людей, і все це безкоштовно.