From 910ecce97286b666f7e68f7f8390cf1bc41a3bc6 Mon Sep 17 00:00:00 2001 From: alireza_sariri Date: Sun, 20 Oct 2024 16:10:01 +0330 Subject: [PATCH 01/16] create financial/price_plus_tax function --- src/financial/mod.rs | 3 +++ src/financial/price_plus_tax.rs | 16 ++++++++++++++++ src/lib.rs | 1 + 3 files changed, 20 insertions(+) create mode 100644 src/financial/mod.rs create mode 100644 src/financial/price_plus_tax.rs diff --git a/src/financial/mod.rs b/src/financial/mod.rs new file mode 100644 index 00000000000..8d6778ba92c --- /dev/null +++ b/src/financial/mod.rs @@ -0,0 +1,3 @@ +mod price_plus_tax; + +pub use price_plus_tax::price_plus_tax; \ No newline at end of file diff --git a/src/financial/price_plus_tax.rs b/src/financial/price_plus_tax.rs new file mode 100644 index 00000000000..4e0c2d5842a --- /dev/null +++ b/src/financial/price_plus_tax.rs @@ -0,0 +1,16 @@ +pub fn price_plus_tax(price: f64, tax_rate: f64) -> f64{ + price * (1 as f64 + tax_rate) +} + + + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_price_plus_tax() { + assert_eq!(131.775,price_plus_tax(125.50, 0.05)); + assert_eq!( 125.0,price_plus_tax(100.0, 0.25)); + } +} diff --git a/src/lib.rs b/src/lib.rs index db12b52b6dd..db33c7157ee 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -19,6 +19,7 @@ pub mod number_theory; pub mod searching; pub mod sorting; pub mod string; +pub mod financial; #[cfg(test)] mod tests { From 3901d8bc85ef0f497ae491db806da53e3f97929b Mon Sep 17 00:00:00 2001 From: alireza_sariri Date: Sat, 26 Oct 2024 09:49:05 +0330 Subject: [PATCH 02/16] run cargo fmt --- src/financial/mod.rs | 2 +- src/financial/price_plus_tax.rs | 12 +++++------- src/lib.rs | 2 +- 3 files changed, 7 insertions(+), 9 deletions(-) diff --git a/src/financial/mod.rs b/src/financial/mod.rs index 8d6778ba92c..42436d54277 100644 --- a/src/financial/mod.rs +++ b/src/financial/mod.rs @@ -1,3 +1,3 @@ mod price_plus_tax; -pub use price_plus_tax::price_plus_tax; \ No newline at end of file +pub use price_plus_tax::price_plus_tax; diff --git a/src/financial/price_plus_tax.rs b/src/financial/price_plus_tax.rs index 4e0c2d5842a..8b88c661db6 100644 --- a/src/financial/price_plus_tax.rs +++ b/src/financial/price_plus_tax.rs @@ -1,8 +1,6 @@ -pub fn price_plus_tax(price: f64, tax_rate: f64) -> f64{ - price * (1 as f64 + tax_rate) -} - - +pub fn price_plus_tax(price: f64, tax_rate: f64) -> f64 { + price * (1_f64 + tax_rate) +} #[cfg(test)] mod tests { @@ -10,7 +8,7 @@ mod tests { #[test] fn test_price_plus_tax() { - assert_eq!(131.775,price_plus_tax(125.50, 0.05)); - assert_eq!( 125.0,price_plus_tax(100.0, 0.25)); + assert_eq!(131.775, price_plus_tax(125.50, 0.05)); + assert_eq!(125.0, price_plus_tax(100.0, 0.25)); } } diff --git a/src/lib.rs b/src/lib.rs index db33c7157ee..fb64d09282a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -8,6 +8,7 @@ pub mod compression; pub mod conversions; pub mod data_structures; pub mod dynamic_programming; +pub mod financial; pub mod general; pub mod geometry; pub mod graph; @@ -19,7 +20,6 @@ pub mod number_theory; pub mod searching; pub mod sorting; pub mod string; -pub mod financial; #[cfg(test)] mod tests { From 603db051950eaec152e28a1f6ad7c3d9add1189c Mon Sep 17 00:00:00 2001 From: alireza_sariri Date: Wed, 30 Oct 2024 09:21:54 +0330 Subject: [PATCH 03/16] add readme.md in financial tax --- src/financial/README.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 src/financial/README.md diff --git a/src/financial/README.md b/src/financial/README.md new file mode 100644 index 00000000000..0b74d6833bd --- /dev/null +++ b/src/financial/README.md @@ -0,0 +1 @@ +## Financial Algorithms From 8e9dbdbbfff388696c7cc7f27a23ce8df6f3c40f Mon Sep 17 00:00:00 2001 From: alireza_sariri Date: Wed, 30 Oct 2024 10:08:55 +0330 Subject: [PATCH 04/16] create present value module add documentation in readme.md --- src/financial/README.md | 4 +++ src/financial/mod.rs | 4 ++- src/financial/present_value.rs | 52 ++++++++++++++++++++++++++++++++++ 3 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 src/financial/present_value.rs diff --git a/src/financial/README.md b/src/financial/README.md index 0b74d6833bd..8ae311e80d3 100644 --- a/src/financial/README.md +++ b/src/financial/README.md @@ -1 +1,5 @@ ## Financial Algorithms +### [Present-Value Algorithm](./present_value.rs) +From [Wikipedia][present-value-wiki]: In economics and finance, present value (PV), also known as present discounted value, is the value of an expected income stream determined as of the date of valuation. The present value is usually less than the future value because money has interest-earning potential, a characteristic referred to as the time value of money, except during times of negative interest rates, when the present value will be equal or more than the future value + +[present-value-wiki]: https://en.wikipedia.org/wiki/Present_value diff --git a/src/financial/mod.rs b/src/financial/mod.rs index 42436d54277..6baa23b2a32 100644 --- a/src/financial/mod.rs +++ b/src/financial/mod.rs @@ -1,3 +1,5 @@ mod price_plus_tax; - +mod present_value; pub use price_plus_tax::price_plus_tax; +pub use present_value::present_value; + diff --git a/src/financial/present_value.rs b/src/financial/present_value.rs new file mode 100644 index 00000000000..569f1a930e5 --- /dev/null +++ b/src/financial/present_value.rs @@ -0,0 +1,52 @@ +#[derive(PartialEq, Eq,Debug)] +pub enum PresentValueError{ + NegetiveDiscount, + EmptyCashFlow +} + + +pub fn present_value(discount_rate: f64, cash_flows: Vec) -> Result { + if discount_rate < 0.0 { + return Err(PresentValueError::NegetiveDiscount); + } + if cash_flows.is_empty() { + return Err(PresentValueError::EmptyCashFlow); + } + + let present_value = cash_flows.iter().enumerate() + .map(|(i, &cash_flow)| cash_flow / (1.0 + discount_rate).powi(i as i32)) + .sum::(); + + Ok((present_value * 100.0).round() / 100.0) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_present_value() { + + assert_eq!(4.69,present_value(0.13, vec![10.0, 20.70, -293.0, 297.0]).unwrap()); + + assert_eq!( -42739.63,present_value(0.07, vec![-109129.39, 30923.23, 15098.93, 29734.0,39.0]).unwrap()); + + assert_eq!(175519.15,present_value(0.07, vec![109129.39, 30923.23, 15098.93, 29734.0,39.0]).unwrap()); + } + + #[test] + fn test_present_value_negative_discount_rate() { + assert_eq!(PresentValueError::NegetiveDiscount,present_value(-1.0, vec![10.0, 20.70, -293.0, 297.0]).unwrap_err()); + + } + + #[test] + fn test_present_value_empty_cash_flow() { + assert_eq!(PresentValueError::EmptyCashFlow,present_value(1.0, vec![]).unwrap_err()); + } + + #[test] + fn test_present_value_zero_discount_rate() { + assert_eq!(184924.55,present_value(0.0, vec![109129.39, 30923.23, 15098.93, 29734.0,39.0]).unwrap()); + } +} From e6392530689cd29cb4744774ab0525ac8bc705ee Mon Sep 17 00:00:00 2001 From: alireza_sariri Date: Wed, 30 Oct 2024 10:14:55 +0330 Subject: [PATCH 05/16] run fmt command --- src/financial/mod.rs | 5 ++-- src/financial/present_value.rs | 43 ++++++++++++++++++++++++---------- 2 files changed, 32 insertions(+), 16 deletions(-) diff --git a/src/financial/mod.rs b/src/financial/mod.rs index 6baa23b2a32..0cb97032f56 100644 --- a/src/financial/mod.rs +++ b/src/financial/mod.rs @@ -1,5 +1,4 @@ -mod price_plus_tax; mod present_value; -pub use price_plus_tax::price_plus_tax; +mod price_plus_tax; pub use present_value::present_value; - +pub use price_plus_tax::price_plus_tax; diff --git a/src/financial/present_value.rs b/src/financial/present_value.rs index 569f1a930e5..cb19ea236f8 100644 --- a/src/financial/present_value.rs +++ b/src/financial/present_value.rs @@ -1,10 +1,9 @@ -#[derive(PartialEq, Eq,Debug)] -pub enum PresentValueError{ +#[derive(PartialEq, Eq, Debug)] +pub enum PresentValueError { NegetiveDiscount, - EmptyCashFlow + EmptyCashFlow, } - pub fn present_value(discount_rate: f64, cash_flows: Vec) -> Result { if discount_rate < 0.0 { return Err(PresentValueError::NegetiveDiscount); @@ -13,7 +12,9 @@ pub fn present_value(discount_rate: f64, cash_flows: Vec) -> Result(); @@ -26,27 +27,43 @@ mod tests { #[test] fn test_present_value() { + assert_eq!( + 4.69, + present_value(0.13, vec![10.0, 20.70, -293.0, 297.0]).unwrap() + ); - assert_eq!(4.69,present_value(0.13, vec![10.0, 20.70, -293.0, 297.0]).unwrap()); - - assert_eq!( -42739.63,present_value(0.07, vec![-109129.39, 30923.23, 15098.93, 29734.0,39.0]).unwrap()); + assert_eq!( + -42739.63, + present_value(0.07, vec![-109129.39, 30923.23, 15098.93, 29734.0, 39.0]).unwrap() + ); - assert_eq!(175519.15,present_value(0.07, vec![109129.39, 30923.23, 15098.93, 29734.0,39.0]).unwrap()); + assert_eq!( + 175519.15, + present_value(0.07, vec![109129.39, 30923.23, 15098.93, 29734.0, 39.0]).unwrap() + ); } #[test] fn test_present_value_negative_discount_rate() { - assert_eq!(PresentValueError::NegetiveDiscount,present_value(-1.0, vec![10.0, 20.70, -293.0, 297.0]).unwrap_err()); - + assert_eq!( + PresentValueError::NegetiveDiscount, + present_value(-1.0, vec![10.0, 20.70, -293.0, 297.0]).unwrap_err() + ); } #[test] fn test_present_value_empty_cash_flow() { - assert_eq!(PresentValueError::EmptyCashFlow,present_value(1.0, vec![]).unwrap_err()); + assert_eq!( + PresentValueError::EmptyCashFlow, + present_value(1.0, vec![]).unwrap_err() + ); } #[test] fn test_present_value_zero_discount_rate() { - assert_eq!(184924.55,present_value(0.0, vec![109129.39, 30923.23, 15098.93, 29734.0,39.0]).unwrap()); + assert_eq!( + 184924.55, + present_value(0.0, vec![109129.39, 30923.23, 15098.93, 29734.0, 39.0]).unwrap() + ); } } From 14491c74b3534015b7141dbd727132902f246171 Mon Sep 17 00:00:00 2001 From: alireza_sariri Date: Sat, 2 Nov 2024 15:03:29 +0330 Subject: [PATCH 06/16] seperate round function in present_value module --- src/financial/README.md | 5 ----- src/financial/present_value.rs | 28 +++++++++++++++++++++++++++- 2 files changed, 27 insertions(+), 6 deletions(-) delete mode 100644 src/financial/README.md diff --git a/src/financial/README.md b/src/financial/README.md deleted file mode 100644 index 8ae311e80d3..00000000000 --- a/src/financial/README.md +++ /dev/null @@ -1,5 +0,0 @@ -## Financial Algorithms -### [Present-Value Algorithm](./present_value.rs) -From [Wikipedia][present-value-wiki]: In economics and finance, present value (PV), also known as present discounted value, is the value of an expected income stream determined as of the date of valuation. The present value is usually less than the future value because money has interest-earning potential, a characteristic referred to as the time value of money, except during times of negative interest rates, when the present value will be equal or more than the future value - -[present-value-wiki]: https://en.wikipedia.org/wiki/Present_value diff --git a/src/financial/present_value.rs b/src/financial/present_value.rs index cb19ea236f8..096c52a10c0 100644 --- a/src/financial/present_value.rs +++ b/src/financial/present_value.rs @@ -18,7 +18,11 @@ pub fn present_value(discount_rate: f64, cash_flows: Vec) -> Result(); - Ok((present_value * 100.0).round() / 100.0) + Ok(round(present_value)) +} + +fn round(value:f64)->f64{ + ( value * 100.0).round() / 100.0 } #[cfg(test)] @@ -66,4 +70,26 @@ mod tests { present_value(0.0, vec![109129.39, 30923.23, 15098.93, 29734.0, 39.0]).unwrap() ); } + #[test] + fn test_round_function() { + + assert_eq!( + 0.55, + round(0.55434) + ); + + assert_eq!( + 10.45, + round(10.453) + ); + + + assert_eq!( + 1111_f64, + round(1111_f64) + ); + + + } + } From b9919e54bb3ef003246602b67b5e16be089abb75 Mon Sep 17 00:00:00 2001 From: alireza_sariri Date: Sat, 2 Nov 2024 16:46:45 +0330 Subject: [PATCH 07/16] remove price_plus_tx use macro for test --- src/financial/mod.rs | 2 - src/financial/present_value.rs | 98 ++++++++++++++++----------------- src/financial/price_plus_tax.rs | 14 ----- 3 files changed, 46 insertions(+), 68 deletions(-) delete mode 100644 src/financial/price_plus_tax.rs diff --git a/src/financial/mod.rs b/src/financial/mod.rs index 0cb97032f56..89b36bfa5e0 100644 --- a/src/financial/mod.rs +++ b/src/financial/mod.rs @@ -1,4 +1,2 @@ mod present_value; -mod price_plus_tax; pub use present_value::present_value; -pub use price_plus_tax::price_plus_tax; diff --git a/src/financial/present_value.rs b/src/financial/present_value.rs index 096c52a10c0..dd7cbfb9143 100644 --- a/src/financial/present_value.rs +++ b/src/financial/present_value.rs @@ -25,71 +25,65 @@ fn round(value:f64)->f64{ ( value * 100.0).round() / 100.0 } + #[cfg(test)] mod tests { use super::*; - #[test] - fn test_present_value() { - assert_eq!( - 4.69, - present_value(0.13, vec![10.0, 20.70, -293.0, 297.0]).unwrap() - ); - - assert_eq!( - -42739.63, - present_value(0.07, vec![-109129.39, 30923.23, 15098.93, 29734.0, 39.0]).unwrap() - ); - - assert_eq!( - 175519.15, - present_value(0.07, vec![109129.39, 30923.23, 15098.93, 29734.0, 39.0]).unwrap() - ); + macro_rules! test_present_value { + ($($name:ident: $inputs:expr,)*) => { + $( + #[test] + fn $name() { + let ((discount_rate,cash_flows), expected) = $inputs; + assert_eq!(present_value(discount_rate,cash_flows).unwrap(), expected); + } + )* + } } - #[test] - fn test_present_value_negative_discount_rate() { - assert_eq!( - PresentValueError::NegetiveDiscount, - present_value(-1.0, vec![10.0, 20.70, -293.0, 297.0]).unwrap_err() - ); + macro_rules! test_present_value_Err { + ($($name:ident: $inputs:expr,)*) => { + $( + #[test] + fn $name() { + let ((discount_rate,cash_flows), expected) = $inputs; + assert_eq!(present_value(discount_rate,cash_flows).unwrap_err(), expected); + } + )* + } } - #[test] - fn test_present_value_empty_cash_flow() { - assert_eq!( - PresentValueError::EmptyCashFlow, - present_value(1.0, vec![]).unwrap_err() - ); + macro_rules! test_round { + ($($name:ident: $inputs:expr,)*) => { + $( + #[test] + fn $name() { + let (input, expected) = $inputs; + assert_eq!(round(input), expected); + } + )* + } } - #[test] - fn test_present_value_zero_discount_rate() { - assert_eq!( - 184924.55, - present_value(0.0, vec![109129.39, 30923.23, 15098.93, 29734.0, 39.0]).unwrap() - ); - } - #[test] - fn test_round_function() { - - assert_eq!( - 0.55, - round(0.55434) - ); - assert_eq!( - 10.45, - round(10.453) - ); + test_present_value!{ + general_inputs1:((0.13, vec![10.0, 20.70, -293.0, 297.0]),4.69), + general_inputs2:((0.07, vec![-109129.39, 30923.23, 15098.93, 29734.0, 39.0]),-42739.63), + general_inputs3:((0.07, vec![109129.39, 30923.23, 15098.93, 29734.0, 39.0]), 175519.15), + zero_input:((0.0, vec![109129.39, 30923.23, 15098.93, 29734.0, 39.0]), 184924.55), - - assert_eq!( - 1111_f64, - round(1111_f64) - ); + } + test_present_value_Err!{ + negative_discount_rate:((-1.0, vec![10.0, 20.70, -293.0, 297.0]), PresentValueError::NegetiveDiscount), + empty_cash_flow:((1.0, vec![]), PresentValueError::EmptyCashFlow), } - + test_round!{ + test1:(0.55434, 0.55), + test2:(10.453, 10.45), + test3:(1111_f64, 1111_f64), + } } + diff --git a/src/financial/price_plus_tax.rs b/src/financial/price_plus_tax.rs deleted file mode 100644 index 8b88c661db6..00000000000 --- a/src/financial/price_plus_tax.rs +++ /dev/null @@ -1,14 +0,0 @@ -pub fn price_plus_tax(price: f64, tax_rate: f64) -> f64 { - price * (1_f64 + tax_rate) -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_price_plus_tax() { - assert_eq!(131.775, price_plus_tax(125.50, 0.05)); - assert_eq!(125.0, price_plus_tax(100.0, 0.25)); - } -} From b38be350b492d02687f91098e22674df5ba2f559 Mon Sep 17 00:00:00 2001 From: alireza_sariri Date: Sat, 2 Nov 2024 16:47:30 +0330 Subject: [PATCH 08/16] use fmt and clippy --- src/financial/present_value.rs | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/src/financial/present_value.rs b/src/financial/present_value.rs index dd7cbfb9143..3d1aa1f2f0c 100644 --- a/src/financial/present_value.rs +++ b/src/financial/present_value.rs @@ -21,11 +21,10 @@ pub fn present_value(discount_rate: f64, cash_flows: Vec) -> Resultf64{ - ( value * 100.0).round() / 100.0 +fn round(value: f64) -> f64 { + (value * 100.0).round() / 100.0 } - #[cfg(test)] mod tests { use super::*; @@ -66,8 +65,7 @@ mod tests { } } - - test_present_value!{ + test_present_value! { general_inputs1:((0.13, vec![10.0, 20.70, -293.0, 297.0]),4.69), general_inputs2:((0.07, vec![-109129.39, 30923.23, 15098.93, 29734.0, 39.0]),-42739.63), general_inputs3:((0.07, vec![109129.39, 30923.23, 15098.93, 29734.0, 39.0]), 175519.15), @@ -75,15 +73,14 @@ mod tests { } - test_present_value_Err!{ + test_present_value_Err! { negative_discount_rate:((-1.0, vec![10.0, 20.70, -293.0, 297.0]), PresentValueError::NegetiveDiscount), empty_cash_flow:((1.0, vec![]), PresentValueError::EmptyCashFlow), } - test_round!{ + test_round! { test1:(0.55434, 0.55), test2:(10.453, 10.45), test3:(1111_f64, 1111_f64), } } - From 7f5b65960fc05b8d406ce8e0020a21b4eee315b0 Mon Sep 17 00:00:00 2001 From: alireza_sariri Date: Sun, 3 Nov 2024 09:46:05 +0330 Subject: [PATCH 09/16] add document to present_value --- src/financial/present_value.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/financial/present_value.rs b/src/financial/present_value.rs index 3d1aa1f2f0c..5294b71758c 100644 --- a/src/financial/present_value.rs +++ b/src/financial/present_value.rs @@ -1,3 +1,8 @@ +/// In economics and finance, present value (PV), also known as present discounted value, +/// is the value of an expected income stream determined as of the date of valuation. +/// +/// -> Wikipedia reference: https://en.wikipedia.org/wiki/Present_value + #[derive(PartialEq, Eq, Debug)] pub enum PresentValueError { NegetiveDiscount, From 7179bc8603a1a7b3dba3d85a7781c7714e48eee5 Mon Sep 17 00:00:00 2001 From: alireza_sariri Date: Wed, 6 Nov 2024 11:30:00 +0330 Subject: [PATCH 10/16] initial electronics module initial coulombs_law module with tests --- src/electronics/coulombs_law.rs | 186 ++++++++++++++++++++++++++++++++ src/electronics/mod.rs | 2 + src/lib.rs | 1 + 3 files changed, 189 insertions(+) create mode 100644 src/electronics/coulombs_law.rs create mode 100644 src/electronics/mod.rs diff --git a/src/electronics/coulombs_law.rs b/src/electronics/coulombs_law.rs new file mode 100644 index 00000000000..408ca757d4a --- /dev/null +++ b/src/electronics/coulombs_law.rs @@ -0,0 +1,186 @@ +/// Apply Coulomb's Law on any three given values. These can be force, charge1, +/// charge2, or distance, and then in a Python dict return name/value pair of +/// the zero value. +/// +/// Coulomb's Law states that the magnitude of the electrostatic force of +/// attraction or repulsion between two point charges is directly proportional +/// to the product of the magnitudes of charges and inversely proportional to +/// the square of the distance between them. +const COULOMBS_CONSTANT: f64 = 8.9875517923e9; +#[derive(PartialEq, Eq, Debug)] +pub enum CoulombsLawError { + ExtraZeroArg(String), + NegativeDistance(String), + NoneZeroArg(String), +} +pub fn coulombs_law( + force: f64, + charge1: f64, + charge2: f64, + distance: f64, +) -> Result { + let charge_product = (charge1 * charge2).abs(); + + if invalid_arguments(force, charge1, charge2, distance) { + return Err(CoulombsLawError::ExtraZeroArg(String::from( + "One and only one argument must be 0", + ))); + } + + if distance < 0.0 { + return Err(CoulombsLawError::NegativeDistance(String::from( + "Distance cannot be negative", + ))); + } + + if force == 0.0 { + return Ok(format!( + "force: {}", + calculate_force(charge_product, distance) + )); + } else if charge1 == 0.0 { + return Ok(format!( + "charge1: {}", + calculate_charge(charge2, force, distance) + )); + } else if charge2 == 0.0 { + return Ok(format!( + "charge2: {}", + calculate_charge(charge1, force, distance) + )); + } else if distance == 0.0 { + return Ok(format!( + "distance: {}", + calculate_distance(charge_product, force) + )); + } + + Err(CoulombsLawError::NoneZeroArg(String::from( + "Exactly one argument must be 0", + ))) +} +fn calculate_distance(charge_product: f64, force: f64) -> f64 { + (COULOMBS_CONSTANT * charge_product / force.abs()).sqrt() +} +fn calculate_charge(charge: f64, force: f64, distance: f64) -> f64 { + force.abs() * distance.powi(2) / (COULOMBS_CONSTANT * charge) +} +fn calculate_force(charge_product: f64, distance: f64) -> f64 { + COULOMBS_CONSTANT * charge_product / distance.powi(2) +} + +fn invalid_arguments(force: f64, charge1: f64, charge2: f64, distance: f64) -> bool { + [force, charge1, charge2, distance] + .iter() + .filter(|&&x| x == 0.0) + .count() + != 1 +} + +#[cfg(test)] +mod tests { + use super::*; + + macro_rules! test_calculate_force { + ($($name:ident: $inputs:expr,)*) => { + $( + #[test] + fn $name() { + let ((charge_product,distance), expected) = $inputs; + assert_eq!(calculate_force(charge_product,distance), expected); + } + )* + } + } + + macro_rules! test_calculate_charge { + ($($name:ident: $inputs:expr,)*) => { + $( + #[test] + fn $name() { + let ((charge,force,distance), expected) = $inputs; + assert_eq!(calculate_charge(charge,force,distance), expected); + } + )* + } + } + macro_rules! test_calculate_distance { + ($($name:ident: $inputs:expr,)*) => { + $( + #[test] + fn $name() { + let ((charge_product,force), expected) = $inputs; + assert_eq!(calculate_distance(charge_product,force), expected); + } + )* + } + } + + macro_rules! test_invalid_arguments { + ($($name:ident: $inputs:expr,)*) => { + $( + #[test] + fn $name() { + let ((force,charge1,charge2,distance), expected) = $inputs; + assert_eq!(invalid_arguments(force,charge1,charge2,distance), expected); + } + )* + } + } + macro_rules! test_coulombs_law { + ($($name:ident: $inputs:expr,)*) => { + $( + #[test] + fn $name() { + let ((force,charge1,charge2,distance), expected) = $inputs; + assert_eq!(coulombs_law(force,charge1,charge2,distance).unwrap(), String::from(expected)); + } + )* + } + } + + macro_rules! test_coulombs_law_err { + ($($name:ident: $inputs:expr,)*) => { + $( + #[test] + fn $name() { + let ((force,charge1,charge2,distance), expected) = $inputs; + assert_eq!(coulombs_law(force,charge1,charge2,distance).unwrap_err(), expected); + } + )* + } + } + + test_coulombs_law! { + general_inputs1:((0.0, 3.0, 5.0, 2000.0), "force: 33703.319221125"), + general_inputs2:((10.0, 3.0, 5.0, 0.0), "distance: 116109.11974711547"), + general_inputs3:((10.0, 0.0, 5.0, 2000.0), "charge1: 0.0008901200443544508"), + general_inputs4:((10.0, 5.0,0.0 , 2000.0), "charge2: 0.0008901200443544508"), + } + + test_coulombs_law_err! { + extra_zero_arg_err: ((0.0, 3.0, 0.0, 2000.0), CoulombsLawError::ExtraZeroArg(String::from("One and only one argument must be 0"))), + negative_distance_err: ((0.0, 3.0, 5.0, -2000.0), CoulombsLawError::NegativeDistance(String::from("Distance cannot be negative"))), + } + + test_invalid_arguments! { + valid_argument_input: ((0.0, 3.0, 5.0, 2000.0), false), + invalid_argument_input: ((0.0, 0.0, 5.0, 2000.0), true), + all_argument_zero: ((0.0, 0.0, 0.0, 0.0), true), + } + + test_calculate_force! { + force_test1: ((15.0,2000.0),33703.319221125), + force_test2: ((18.0,0.12),11234439740375.0), + } + + test_calculate_charge! { + charge_test1: ((15.0,6.0,2000.0),0.00017802400887089018), + charge_test2: ((18.0,3.0,0.12),2.6703601330633526e-13), + } + + test_calculate_distance! { + distance_test1: ((15.0,5.0),164203.09186157244), + distance_test2: ((18.0,11.0),121272.02040394374), + } +} diff --git a/src/electronics/mod.rs b/src/electronics/mod.rs new file mode 100644 index 00000000000..2681de2cc05 --- /dev/null +++ b/src/electronics/mod.rs @@ -0,0 +1,2 @@ +mod coulombs_law; +pub use coulombs_law::coulombs_law; diff --git a/src/lib.rs b/src/lib.rs index fb64d09282a..3254acc8e42 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -8,6 +8,7 @@ pub mod compression; pub mod conversions; pub mod data_structures; pub mod dynamic_programming; +pub mod electronics; pub mod financial; pub mod general; pub mod geometry; From 527a6a6ea4fcdf7b04fab4663d00c04a45803dc6 Mon Sep 17 00:00:00 2001 From: alireza_sariri Date: Wed, 6 Nov 2024 11:31:29 +0330 Subject: [PATCH 11/16] add wikipedia refrence to doc --- src/electronics/coulombs_law.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/electronics/coulombs_law.rs b/src/electronics/coulombs_law.rs index 408ca757d4a..0190b797d57 100644 --- a/src/electronics/coulombs_law.rs +++ b/src/electronics/coulombs_law.rs @@ -6,6 +6,9 @@ /// attraction or repulsion between two point charges is directly proportional /// to the product of the magnitudes of charges and inversely proportional to /// the square of the distance between them. +/// +/// -> Wikipedia reference: https://en.wikipedia.org/wiki/Coulomb%27s_law + const COULOMBS_CONSTANT: f64 = 8.9875517923e9; #[derive(PartialEq, Eq, Debug)] pub enum CoulombsLawError { From 5b1f537e555479899650b0f2c186419a5420e0c5 Mon Sep 17 00:00:00 2001 From: alireza_sariri Date: Wed, 6 Nov 2024 13:16:07 +0330 Subject: [PATCH 12/16] initial matrix initial search_in_a_sorted_matrix with tests --- src/lib.rs | 1 + src/matrix/mod.rs | 2 + src/matrix/search_in_a_sorted_matrix.rs | 98 +++++++++++++++++++++++++ 3 files changed, 101 insertions(+) create mode 100644 src/matrix/mod.rs create mode 100644 src/matrix/search_in_a_sorted_matrix.rs diff --git a/src/lib.rs b/src/lib.rs index 3254acc8e42..ba5b3b529ce 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -16,6 +16,7 @@ pub mod graph; pub mod greedy; pub mod machine_learning; pub mod math; +pub mod matrix; pub mod navigation; pub mod number_theory; pub mod searching; diff --git a/src/matrix/mod.rs b/src/matrix/mod.rs new file mode 100644 index 00000000000..ba394113d3a --- /dev/null +++ b/src/matrix/mod.rs @@ -0,0 +1,2 @@ +mod search_in_a_sorted_matrix; +pub use search_in_a_sorted_matrix::search_in_a_sorted_matrix; diff --git a/src/matrix/search_in_a_sorted_matrix.rs b/src/matrix/search_in_a_sorted_matrix.rs new file mode 100644 index 00000000000..788ac8b6f19 --- /dev/null +++ b/src/matrix/search_in_a_sorted_matrix.rs @@ -0,0 +1,98 @@ + + +///find row and column of given key in given matrix +/// m is row count and n is column count +#[derive(PartialEq, Eq, Debug)] +pub struct SortedMatrixResult { + pub column: i64, + pub row: i64, +} +#[derive(PartialEq, Eq, Debug)] +pub enum SortedMatrixErr { + KeyNotFound, + InvalidArgument(String), +} +pub fn search_in_a_sorted_matrix( + mat: Vec>, + m: usize, + n: usize, + key: f64, +) -> Result { + if m < 1 { + return Err(SortedMatrixErr::InvalidArgument(String::from( + "m must be greater than or equal to 1", + ))); + } + + if n < 1 { + return Err(SortedMatrixErr::InvalidArgument(String::from( + "n must be greater than or equal to 1", + ))); + } + + if mat.is_empty() { + return Err(SortedMatrixErr::InvalidArgument(String::from( + "mat must be non-empty", + ))); + } + + let (mut i, mut j) = (m - 1, 0); + + while j < n { + if (mat[i][j] - key).abs() < f64::EPSILON { + return Ok(SortedMatrixResult { + column: (j + 1) as i64, + row: (i + 1) as i64, + }); + } + if key < mat[i][j] { + i -= 1; + } else { + j += 1; + } + } + Err(SortedMatrixErr::KeyNotFound) +} +#[cfg(test)] +mod tests { + use super::*; + macro_rules! test_search_in_a_sorted_matrix_err { + ($($name:ident: $inputs:expr,)*) => { + $( + #[test] + fn $name() { + let ((mat,m,n,key), expected) = $inputs; + assert_eq!(search_in_a_sorted_matrix(mat,m,n,key).unwrap_err(), expected); + } + )* + } + } + macro_rules! test_search_in_a_sorted_matrix { + ($($name:ident: $inputs:expr,)*) => { + $( + #[test] + fn $name() { + let ((mat,m,n,key), expected) = $inputs; + assert_eq!(search_in_a_sorted_matrix(mat,m,n,key).unwrap(), expected); + } + )* + } + } + + test_search_in_a_sorted_matrix_err! { + key_not_found_test: ((vec![vec![1.0,1.0],vec![1.0,1.0]],2,2,4.0), SortedMatrixErr::KeyNotFound), + invalid_m_test: ((vec![vec![1.0,1.0],vec![1.0,1.0]],0,2,4.0), SortedMatrixErr::InvalidArgument(String::from("m must be greater than or equal to 1"))), + invalid_n_test: ((vec![vec![1.0,1.0],vec![1.0,1.0]],2,0,4.0), SortedMatrixErr::InvalidArgument(String::from("n must be greater than or equal to 1"))), + } + + test_search_in_a_sorted_matrix! { + kgeneral_test1: ((vec![vec![2.1, 5.0, 7.0], vec![4.0, 8.0, 13.0], vec![9.0, 11.0, 15.0], vec![12.0, 17.0, 20.0]], 3, 3, 2.1), SortedMatrixResult{ + row:1, + column:1 + }), + kgeneral_test2: (( vec![vec![2.0, 5.0, 7.0], vec![4.0, 8.0, 13.0], vec![9.0, 11.0, 15.0], vec![12.0, 17.0, 20.0]], 3, 3, 5.0), SortedMatrixResult{ + row:1, + column:2 + }), + } +} From 4f862f3488bb18c5417010e96a40b367bb68ce4f Mon Sep 17 00:00:00 2001 From: alireza_sariri Date: Wed, 6 Nov 2024 13:17:40 +0330 Subject: [PATCH 13/16] set space at top of search in sorted matrix module --- src/matrix/search_in_a_sorted_matrix.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/matrix/search_in_a_sorted_matrix.rs b/src/matrix/search_in_a_sorted_matrix.rs index 788ac8b6f19..256d102d5c7 100644 --- a/src/matrix/search_in_a_sorted_matrix.rs +++ b/src/matrix/search_in_a_sorted_matrix.rs @@ -1,5 +1,3 @@ - - ///find row and column of given key in given matrix /// m is row count and n is column count #[derive(PartialEq, Eq, Debug)] From f907fea593e568a4707d6425d7516c0a7779e8b3 Mon Sep 17 00:00:00 2001 From: alireza_sariri Date: Fri, 8 Nov 2024 11:19:38 +0330 Subject: [PATCH 14/16] remove unreachable code in coulombs law --- src/electronics/coulombs_law.rs | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/electronics/coulombs_law.rs b/src/electronics/coulombs_law.rs index 0190b797d57..fc8d9d70947 100644 --- a/src/electronics/coulombs_law.rs +++ b/src/electronics/coulombs_law.rs @@ -14,7 +14,6 @@ const COULOMBS_CONSTANT: f64 = 8.9875517923e9; pub enum CoulombsLawError { ExtraZeroArg(String), NegativeDistance(String), - NoneZeroArg(String), } pub fn coulombs_law( force: f64, @@ -51,16 +50,12 @@ pub fn coulombs_law( "charge2: {}", calculate_charge(charge1, force, distance) )); - } else if distance == 0.0 { + } else { return Ok(format!( "distance: {}", calculate_distance(charge_product, force) )); } - - Err(CoulombsLawError::NoneZeroArg(String::from( - "Exactly one argument must be 0", - ))) } fn calculate_distance(charge_product: f64, force: f64) -> f64 { (COULOMBS_CONSTANT * charge_product / force.abs()).sqrt() From ce72ad3e027d6d9662c29134be7133e3f9e8eb9d Mon Sep 17 00:00:00 2001 From: alireza_sariri Date: Fri, 8 Nov 2024 11:25:19 +0330 Subject: [PATCH 15/16] run clippy in coulombs law --- src/electronics/coulombs_law.rs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/electronics/coulombs_law.rs b/src/electronics/coulombs_law.rs index fc8d9d70947..5704a0dbea3 100644 --- a/src/electronics/coulombs_law.rs +++ b/src/electronics/coulombs_law.rs @@ -50,12 +50,11 @@ pub fn coulombs_law( "charge2: {}", calculate_charge(charge1, force, distance) )); - } else { - return Ok(format!( - "distance: {}", - calculate_distance(charge_product, force) - )); } + Ok(format!( + "distance: {}", + calculate_distance(charge_product, force) + )) } fn calculate_distance(charge_product: f64, force: f64) -> f64 { (COULOMBS_CONSTANT * charge_product / force.abs()).sqrt() From 804daf4694face6bcbf88e9c0399a0408c7a58bf Mon Sep 17 00:00:00 2001 From: alireza_sariri Date: Fri, 8 Nov 2024 11:29:26 +0330 Subject: [PATCH 16/16] write test for empty matrix --- src/matrix/search_in_a_sorted_matrix.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/matrix/search_in_a_sorted_matrix.rs b/src/matrix/search_in_a_sorted_matrix.rs index 256d102d5c7..3af78101c0c 100644 --- a/src/matrix/search_in_a_sorted_matrix.rs +++ b/src/matrix/search_in_a_sorted_matrix.rs @@ -81,6 +81,7 @@ mod tests { key_not_found_test: ((vec![vec![1.0,1.0],vec![1.0,1.0]],2,2,4.0), SortedMatrixErr::KeyNotFound), invalid_m_test: ((vec![vec![1.0,1.0],vec![1.0,1.0]],0,2,4.0), SortedMatrixErr::InvalidArgument(String::from("m must be greater than or equal to 1"))), invalid_n_test: ((vec![vec![1.0,1.0],vec![1.0,1.0]],2,0,4.0), SortedMatrixErr::InvalidArgument(String::from("n must be greater than or equal to 1"))), + invalid_mat_test: ((vec![],2,1,4.0), SortedMatrixErr::InvalidArgument(String::from("mat must be non-empty"))), } test_search_in_a_sorted_matrix! {