Skip to content

Instantly share code, notes, and snippets.

@voxxal
Last active April 19, 2022 20:19
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save voxxal/223583e71689a15fb1edc25e271eae7c to your computer and use it in GitHub Desktop.

Binomial Probability

Exercise to learn more about rust's type system. If you know a way to implement a trait on all itertors please tell me.

use std::ops::Range;
enum ConditionType {
Number,
Closure,
Range,
}
trait Condition {
fn r#type(&self) -> ConditionType;
fn as_num(&self) -> i32 {
unreachable!();
}
fn as_closure(&self) -> &dyn Fn(i32) -> bool {
unreachable!();
}
fn as_range(&self) -> Range<i32> {
unreachable!();
}
}
impl Condition for i32 {
fn r#type(&self) -> ConditionType {
ConditionType::Number
}
fn as_num(&self) -> i32 {
*self
}
}
impl<F> Condition for F where F: Fn(i32) -> bool {
fn r#type(&self) -> ConditionType {
ConditionType::Closure
}
fn as_closure(&self) -> &dyn Fn(i32) -> bool {
self
}
}
impl Condition for Range<i32> {
fn r#type(&self) -> ConditionType {
ConditionType::Range
}
fn as_range(&self) -> Range<i32> {
self.clone()
}
}
fn factorial(n: i32) -> i32 {
match n {
0 => 1,
_ => factorial(n - 1) * n,
}
}
fn choose(n: i32, r: i32) -> i32 {
factorial(n) / (factorial(r) * factorial(n - r))
}
fn binomial_probability(condition: impl Condition, total: i32, prob: f64) -> f64 {
match condition.r#type() {
ConditionType::Number => choose(total, condition.as_num()) as f64 * prob.powi(condition.as_num()) * (1. - prob).powi(total - condition.as_num()),
ConditionType::Closure => {
let mut res: f64 = 0.0;
for i in 0..=total {
if condition.as_closure()(i) {
res += binomial_probability(i, total, prob);
}
}
res
},
ConditionType::Range => {
let mut res: f64 = 0.0;
for i in condition.as_range() {
if(i <= total) { res += binomial_probability(i, total, prob); }
}
res
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment