2020-09-14 18:29:36 +00:00
|
|
|
//! Helper function for random number generator
|
2022-03-12 20:31:30 +00:00
|
|
|
//!
|
2020-09-14 18:29:36 +00:00
|
|
|
use rand::prelude::*;
|
|
|
|
|
2020-09-15 20:33:18 +00:00
|
|
|
pub trait Rng {
|
|
|
|
/// Generate random number between start and end (bot inclusive).
|
|
|
|
fn roll_dice(&mut self, min: usize, max: usize) -> usize;
|
|
|
|
/// Generate random number between start (inclusive) and end (exclusive).
|
|
|
|
fn random_range(&mut self, start: usize, end: usize) -> usize;
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Rng for StdRng {
|
|
|
|
fn roll_dice(&mut self, min: usize, max: usize) -> usize {
|
2022-03-12 20:31:30 +00:00
|
|
|
self.random_range(min, max + 1)
|
2020-09-15 20:33:18 +00:00
|
|
|
}
|
2020-09-14 18:29:36 +00:00
|
|
|
|
2020-09-15 20:33:18 +00:00
|
|
|
fn random_range(&mut self, start: usize, end: usize) -> usize {
|
|
|
|
let max = (end - start) as u32;
|
|
|
|
if max == 0 {
|
|
|
|
start
|
|
|
|
} else {
|
|
|
|
((self.next_u32() % max) + start as u32) as usize
|
|
|
|
}
|
2020-09-15 14:23:47 +00:00
|
|
|
}
|
2020-09-14 18:29:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// ------------------------------------------------------------------------------------------------
|
|
|
|
/// Module unit tests
|
|
|
|
/// ------------------------------------------------------------------------------------------------
|
|
|
|
#[cfg(test)]
|
|
|
|
mod tests {
|
2020-09-15 20:33:18 +00:00
|
|
|
use super::Rng;
|
2022-03-12 20:31:30 +00:00
|
|
|
use rand::prelude::*;
|
2020-09-14 18:29:36 +00:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_range() {
|
2020-09-15 20:33:18 +00:00
|
|
|
let mut rng = StdRng::seed_from_u64(100);
|
|
|
|
let x = rng.random_range(5, 8);
|
2020-09-14 18:36:07 +00:00
|
|
|
assert!(x >= 5 && x < 8);
|
2020-09-14 18:29:36 +00:00
|
|
|
}
|
|
|
|
|
2020-09-15 20:33:18 +00:00
|
|
|
#[test]
|
|
|
|
fn test_range_average() {
|
2021-01-12 16:27:33 +00:00
|
|
|
let num_op = 10000;
|
2020-09-15 20:33:18 +00:00
|
|
|
let mut rng = StdRng::seed_from_u64(1000);
|
|
|
|
let xs: Vec<usize> = (0..num_op).map(|_| rng.random_range(5, 10)).collect();
|
|
|
|
let mean = xs.iter().sum::<usize>() / num_op;
|
|
|
|
let min = *xs.iter().min().expect("no min");
|
|
|
|
let max = *xs.iter().max().expect("no max");
|
|
|
|
assert_eq!(mean, 7);
|
|
|
|
assert_eq!(min, 5);
|
|
|
|
assert_eq!(max, 9);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_roll_dice() {
|
|
|
|
let num_op = 1000;
|
|
|
|
let mut rng = StdRng::seed_from_u64(2000);
|
|
|
|
let xs: Vec<usize> = (0..num_op).map(|_| rng.roll_dice(1, 7)).collect();
|
|
|
|
let mean = xs.iter().sum::<usize>() as f32 / num_op as f32 + 0.5;
|
|
|
|
let min = *xs.iter().min().expect("no min");
|
|
|
|
let max = *xs.iter().max().expect("no max");
|
|
|
|
assert_eq!(mean as usize, 4);
|
|
|
|
assert_eq!(min, 1);
|
|
|
|
assert_eq!(max, 7);
|
|
|
|
}
|
2022-03-12 20:31:30 +00:00
|
|
|
}
|