упр.07 задача 1

Предадени решения

Краен срок:
26.11.2025 23:59
Точки:
4

Срокът за предаване на решения е отминал

// Include the solution source in the same file, so we
// don't have to worry about item visibility.
// Please don't use `include!` in real code, this is a hack
// around the checking system.
include!{ "../src/lib.rs" }
#[test]
fn test_adapters_() {
let iter = iter_filter(0..10, |&x| x % 2 == 0);
assert_eq!(iter.collect::<Vec<i32>>(), vec![0, 2, 4, 6, 8]);
let iter = iter_map(5..10, |x| x * x);
assert_eq!(iter.collect::<Vec<i32>>(), vec![25, 36, 49, 64, 81]);
let iter = iter_filter_map(0..10, |x| if x % 2 == 0 { Some(x * x) } else { None });
assert_eq!(iter.collect::<Vec<i32>>(), vec![0, 4, 16, 36, 64]);
}
#[test]
fn test_text_parsers_() {
let text = r#"
-10
20
30
40
"#;
assert_eq!(get_sum(text), 80);
assert_eq!(get_num_list(text), Ok(vec![-10, 20, 30, 40]));
let text = r#"
123
-48
baba
0
"#;
assert_eq!(get_sum(text), 75);
assert_eq!(get_num_list(text), Err(FoundWord("baba")));
}

Част 1

Забележка: за тази част нямате право да използвате методи от Iterator различни от next()

Имплементирайте адаптер, който работи подобно на метода Iterator::map().
Имплементирайте функция iter_map, която приема:

  • iter: итератор с елементи от тип T
  • f: функция T -> U

и връща итератор, който прилага f върху всеки пореден елемент от iter.
Функцията iter_map трябва да работи мързеливо и се очаква единствено да конструира инстанция на структура Map. Същината на имплементацията се очаква да бъде в имплементацията на trait Iterator. Добавете необходимите типове параметри и trait bounds, където се налага.

struct Map<???> {
    /* ... */
}

fn iter_map<I, F, U>(iter: I, f: F) -> Map<???>
where
    I: Iterator,
    F: Fn(I::Item) -> U
{
    todo!()
}

impl<I, F, U> Iterator for Map<???> {
    type Item = U;

    fn next(&mut self) -> Option<Self::Item> {
        todo!()
    }
}

По подобен начин имплементирайте адаптер, подобен на метода Iterator::filter(). Имплементирайте функция iter_filter, която приема:

  • iter: итератор с елементи от тип T
  • f: функция &T -> bool

и връща итератор, който връща само елементите от iter, за които f връща true.

struct Filter<???> {
    /* ... */
}

fn iter_filter<I, F>(iter: I, func: F) -> Filter<I, F>
where
    I: Iterator,
    F: Fn(&I::Item) -> bool,
{
    todo!()
}

impl<I, F> Iterator for Filter<???> {
    type Item = I::Item;

    fn next(&mut self) -> Option<Self::Item> {
        todo!()
    }
}

Част 2

Имплементирайте следния адаптер, използвайки само iter_map и iter_filter

Имплементирайте адаптер iter_filter_map, който приема:

  • iter: итератор с елементи от тип T
  • f: функция T -> Option<U>

и връща итератор, който прилага f върху елементите от iter и връща резултатите, които не са None.

Подсказка: използвайте композиция на функциите iter_filter и iter_map. Внимавайте какъв итератор връщат тези функции и какъв му е Item типа.

Обяснете в коментар защо връщаме impl Iterator и ако не правехме това, какъв би бил конкретния тип на резултата.

fn iter_filter_map<I, F, U>(iter: I, func: F) -> impl Iterator<Item = U>
where
    I: Iterator,
    F: Fn(I::Item) -> Option<U>,
{
    todo!()
}

Част 3

Имплементирайте следните функции, без да използвате for/while/loop цикъл.
Можете да използвате адаптерите имплементирани по-горе, както и всички останали методи на Iterator, за които не сме написали собствена имплементация.

Функцията работи с парче текст, съдържащо по най-много едно число или дума на ред. Текста също може да съдържа произволни whitespace символи (щпации и табулации) и празни редове.

Функцията се очаква да върне сумата от всички числа в текста, игнорирайки думите и празните редове.

fn get_sum(text: &str) -> i32 {
    todo!()
}

Друга функция работи със същото парче текст. Тя проверява, че текста не съдържа думи и връща списък от всички числа в текста. Ако намери дума в текста връща грешка FoundWord, съдържата намерената дума.

Можете да иползвате следната имплементация на типаж FromIterator за Result.
Тя позволява върху Iterator<Item = Result<A, E>> да извикате collect::<Result<Vec<A>, E>>.

#[derive(Debug, Eq, PartialEq)]
struct FoundWord<'a>(&'a str);

fn get_num_list(text: &str) -> Result<Vec<i32>, FoundWord<'_>> {
    todo!()
}

Задължително прочетете (или си припомнете): Указания за предаване на домашни

Погрижете се решението ви да се компилира с базовия тест:

// Include the solution source in the same file, so we
// don't have to worry about item visibility.
// Please don't use `include!` in real code, this is a hack
// around the checking system.
include!{ "../src/lib.rs" }
#[test]
fn test_adapters() {
let iter = iter_filter(0..10, |&x| x % 2 == 0);
assert_eq!(iter.collect::<Vec<i32>>(), vec![0, 2, 4, 6, 8]);
let iter = iter_map(5..10, |x| x * x);
assert_eq!(iter.collect::<Vec<i32>>(), vec![25, 36, 49, 64, 81]);
let iter = iter_filter_map(0..10, |x| if x % 2 == 0 { Some(x * x) } else { None });
assert_eq!(iter.collect::<Vec<i32>>(), vec![0, 4, 16, 36, 64]);
}
#[test]
fn test_text_parsers() {
let text = r#"
-10
20
30
40
"#;
assert_eq!(get_sum(text), 80);
assert_eq!(get_num_list(text), Ok(vec![-10, 20, 30, 40]));
let text = r#"
123
-48
baba
0
"#;
assert_eq!(get_sum(text), 75);
assert_eq!(get_num_list(text), Err(FoundWord("baba")));
}