تمرین: شمارنده

در این تمرین، شما یک ساختار داده بسیار ساده را به‌صورت generic خواهید کرد. این ساختار از std::collections::HashMap برای پیگیری اینکه چه مقادیری مشاهده شده‌اند و هرکدام چند بار ظاهر شده‌اند، استفاده می‌کند.

نسخه اولیه Counter به‌طور سخت‌افزاری برای مقادیر u32 کدگذاری شده است. ساختار و متدهای آن را به‌صورت generic بر اساس تایپ مقداری که در حال پیگیری است، تغییر دهید، به‌طوری که Counter بتواند هر تایپ مقداری را پیگیری کند.

اگر زود تمام کردید، سعی کنید از متد entry استفاده کنید تا تعداد جستجوهای هش مورد نیاز برای پیاده‌سازی متد count را به نصف کاهش دهید.

use std::collections::HashMap;

/// Counter counts the number of times each value of type T has been seen.
struct Counter {
    values: HashMap<u32, u64>,
}

impl Counter {
    /// Create a new Counter.
    fn new() -> Self {
        Counter {
            values: HashMap::new(),
        }
    }

    /// Count an occurrence of the given value.
    fn count(&mut self, value: u32) {
        if self.values.contains_key(&value) {
            *self.values.get_mut(&value).unwrap() += 1;
        } else {
            self.values.insert(value, 1);
        }
    }

    /// Return the number of times the given value has been seen.
    fn times_seen(&self, value: u32) -> u64 {
        self.values.get(&value).copied().unwrap_or_default()
    }
}

fn main() {
    let mut ctr = Counter::new();
    ctr.count(13);
    ctr.count(14);
    ctr.count(16);
    ctr.count(14);
    ctr.count(14);
    ctr.count(11);

    for i in 10..20 {
        println!("مقادیر {} برابر با {} را دیده‌شده", ctr.times_seen(i), i);
    }

    let mut strctr = Counter::new();
    strctr.count("سیب");
    strctr.count("orange");
    strctr.count("سیب");
    println!("داشتم {} سیب‌ها", strctr.times_seen("سیب"));
}