extern crate rand;
use std::env;
use std::fmt::Debug;
use std::iter::FromIterator;
use self::rand::{thread_rng, seq, Rng};
const MAX_SIMS: u32 = 100_000;
pub struct Bag<T: Clone> {
pub items: Vec<T>,
pub max_sims: u32
}
fn get_default_max_sims() -> u32 {
match env::var("MENDEL_MAX_SIMS") {
Ok(val) => val.parse::<u32>().unwrap(),
Err(_) => MAX_SIMS
}
}
impl<T: Clone> Bag<T> {
pub fn from_range(min: i32, max: i32) -> Self where
Vec<T>: FromIterator<i32> {
let items: Vec<T> = (min..max).collect();
Bag { items, max_sims: get_default_max_sims() }
}
pub fn from_vec(v: Vec<T>) -> Self {
let items: Vec<T> = v.clone();
Bag { items, max_sims: get_default_max_sims() }
}
pub fn one<F>(&self, f: F) -> f64 where
F: Fn(&T) -> bool {
let mut picks_in_favor: u32 = 0;
for _ in 0..self.max_sims {
let idx = thread_rng().gen_range(0, self.items.len());
let item = &self.items[idx];
if f(item) {
picks_in_favor += 1;
}
}
picks_in_favor as f64 / MAX_SIMS as f64
}
pub fn sample<F>(&self, sample_size: usize, f: F) -> f64 where
T: Debug,
F: Fn(Vec<&T>) -> bool {
let mut picks_in_favor: u32 = 0;
let mut rng = thread_rng();
let items_clone = self.items.clone();
for _ in 0..self.max_sims {
let sample = seq::sample_iter(&mut rng, &items_clone, sample_size).unwrap();
if f(sample) {
picks_in_favor += 1;
}
}
picks_in_favor as f64 / MAX_SIMS as f64
}
pub fn set_max_sims(&mut self, max_sims: u32) -> () {
self.max_sims = max_sims;
}
}