1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
use mersenne_twister::MT19937_64;
use rand::{Rng, SeedableRng};

#[no_mangle]
pub fn experiments(seed: u64, variants: &Vec<u8>) -> Vec<u8> {
    let mut rng: MT19937_64 = SeedableRng::from_seed(seed);
    variants.into_iter().map(|&max| {
        rng.gen_range(0, max)
    }).collect()
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::convert::TryInto;

    fn generate_variant_max(n: u64) -> Vec<u8> {
        (0..n).map(|_| { 255 }).collect()
    }

    #[test]
    fn length_is_same_as_variants() {
        let n = 100;
        let result: Vec<u8> = experiments(0, &generate_variant_max(n));
        assert_eq!(result.len() , 100);
    }

    #[test]
    fn different_seeds_give_different_output() {
        let first: Vec<u8> = experiments(0, &generate_variant_max(100));
        let second: Vec<u8> = experiments(9_223_372_036_854_775_807, &generate_variant_max(100));
        assert_ne!(first, second);
    }

    #[test]
    fn around_half_of_experiments_above_128() {
        let n = 100_000;
        let result: Vec<u8> = experiments(0, &generate_variant_max(n));
        let sum: i128 = result.into_iter()
            .map(|exp_val| if exp_val > 128 {1} else {0})
            .fold(0, |acc, x| acc + x);
        let t: i128 = n.try_into().unwrap();
        let tolerence = t / 16;
        let tolerated = if (sum - (t / 2)).abs() < tolerence { true } else { false };
        assert_eq!(tolerated, true);
    }
    
}