random_name_generator 0.4.0

Random Name Generator
Documentation
use rand::distr::{Distribution, weighted::WeightedIndex};
use std::sync::LazyLock;

pub static NORMAL_WEIGHT: LazyLock<WeightedRnd> = LazyLock::new(|| WeightedRnd {
    counts: vec![2, 3, 4, 5],
    weights: vec![4, 10, 3, 1],
});
pub static SHORT_WEIGHT: LazyLock<WeightedRnd> = LazyLock::new(|| WeightedRnd {
    counts: vec![2, 3],
    weights: vec![4, 1],
});

pub struct WeightedRnd {
    pub counts: Vec<u8>,
    pub weights: Vec<u8>,
}

impl WeightedRnd {
    pub fn random(&self) -> u8 {
        let dist = WeightedIndex::new(self.weights.as_slice())
            .expect("weights are non-empty and positive");
        let mut rng = rand::rng();
        self.counts.as_slice()[dist.sample(&mut rng)]
    }
}

#[cfg(test)]
mod test_language {
    use super::*;

    #[test]
    fn normal_weight() {
        let chain: Vec<u8> = (1..100).map(|_| NORMAL_WEIGHT.random()).collect();
        let non: Vec<u8> = vec![0, 1, 6, 7, 8];

        chain
            .iter()
            .for_each(|i| assert!(NORMAL_WEIGHT.counts.contains(i)));
        chain.iter().for_each(|i| assert!(!non.contains(i)));
    }

    #[test]
    fn short_weight() {
        let chain: Vec<u8> = (1..100).map(|_| SHORT_WEIGHT.random()).collect();
        let non: Vec<u8> = vec![0, 1, 4, 5, 6];

        chain
            .iter()
            .for_each(|i| assert!(SHORT_WEIGHT.counts.contains(i)));
        chain.iter().for_each(|i| assert!(!non.contains(i)));
    }
}