use rand::Rng;
use statistical;
use std::{
sync::{self, mpsc::Sender},
thread,
};
fn calculate(number_of_loops: i32, sender: Option<Sender<Option<Vec<i32>>>>) -> Option<Vec<i32>> {
match number_of_loops {
0 => {
match sender {
Some(tx) => tx.send(None).unwrap(),
None => (),
}
None
}
_ => {
let mut probability: Vec<i32> = Vec::new();
for _i in 0..number_of_loops {
let mut prizes: [i32; 6] = [0, 0, 0, 0, 0, 0];
let mut opens: i32 = 0;
while prizes.contains(&0) {
prizes[rand::thread_rng().gen_range(0, 6)] += 1;
opens += 1
}
probability.push(opens)
}
probability.shrink_to_fit();
let probability = Some(probability);
match sender {
Some(tx) => tx.send(probability.clone()).unwrap(),
None => (),
}
probability
}
}
}
pub fn simulation(number_of_loops: i32, number_of_threads: i32) -> Vec<i32> {
if number_of_loops < 0 {
panic!(
"Set number of loops greater than -1. You set it to {}.",
number_of_loops
)
} else if number_of_threads < 0 {
panic!(
"Set number of threads greater than -1. You set it to {}",
number_of_threads
)
}
match number_of_loops {
0 => vec![0],
_ => {
let child_load = (number_of_loops as f32 / number_of_threads as f32).floor() as i32;
let (tx, rx) = sync::mpsc::channel();
for _i in 0..number_of_threads {
let tx_clone = sync::mpsc::Sender::clone(&tx);
let child_load_clone = child_load.clone();
thread::spawn(move || calculate(child_load_clone, Some(tx_clone)));
}
let load = (number_of_loops as f32 / number_of_threads as f32).ceil() as i32;
calculate(load, Some(tx));
let mut probability = Vec::new();
for data in rx {
match data {
Some(mut vec) => {
probability.append(&mut vec);
}
None => (),
}
}
probability
}
}
}
pub fn simulation_single_thread(number_of_loops: i32) -> Vec<i32> {
if number_of_loops < 0 {
panic!(
"Set number of loops greater than -1. You set it to {}.",
number_of_loops
)
}
match number_of_loops {
0 => vec![0],
_ => calculate(number_of_loops, None).unwrap(),
}
}
pub fn statistics(data: Vec<i32>) -> (f64, i32, i32, i32) {
let mut floating_data = Vec::new();
for datum in data.clone() {
floating_data.push(datum as f64)
}
let mean: f64 = statistical::mean(floating_data.as_slice());
let median = statistical::median(data.as_slice());
let max = data.iter().max().unwrap();
let min = data.iter().min().unwrap();
(mean, median, *max, *min)
}