Skip to content

Commit a5b0712

Browse files
authored
Merge branch 'master' into ref/graph/kruskal
2 parents ae5811d + e92ab20 commit a5b0712

File tree

5 files changed

+155
-9
lines changed

5 files changed

+155
-9
lines changed

DIRECTORY.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,8 @@
101101
* [Subset Generation](https://github.com/TheAlgorithms/Rust/blob/master/src/dynamic_programming/subset_generation.rs)
102102
* [Trapped Rainwater](https://github.com/TheAlgorithms/Rust/blob/master/src/dynamic_programming/trapped_rainwater.rs)
103103
* [Word Break](https://github.com/TheAlgorithms/Rust/blob/master/src/dynamic_programming/word_break.rs)
104+
* Financial
105+
* [Present Value](https://github.com/TheAlgorithms/Rust/blob/master/src/financial/present_value.rs)
104106
* General
105107
* [Convex Hull](https://github.com/TheAlgorithms/Rust/blob/master/src/general/convex_hull.rs)
106108
* [Fisher Yates Shuffle](https://github.com/TheAlgorithms/Rust/blob/master/src/general/fisher_yates_shuffle.rs)

src/financial/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
mod present_value;
2+
pub use present_value::present_value;

src/financial/present_value.rs

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
/// In economics and finance, present value (PV), also known as present discounted value,
2+
/// is the value of an expected income stream determined as of the date of valuation.
3+
///
4+
/// -> Wikipedia reference: https://en.wikipedia.org/wiki/Present_value
5+
6+
#[derive(PartialEq, Eq, Debug)]
7+
pub enum PresentValueError {
8+
NegetiveDiscount,
9+
EmptyCashFlow,
10+
}
11+
12+
pub fn present_value(discount_rate: f64, cash_flows: Vec<f64>) -> Result<f64, PresentValueError> {
13+
if discount_rate < 0.0 {
14+
return Err(PresentValueError::NegetiveDiscount);
15+
}
16+
if cash_flows.is_empty() {
17+
return Err(PresentValueError::EmptyCashFlow);
18+
}
19+
20+
let present_value = cash_flows
21+
.iter()
22+
.enumerate()
23+
.map(|(i, &cash_flow)| cash_flow / (1.0 + discount_rate).powi(i as i32))
24+
.sum::<f64>();
25+
26+
Ok(round(present_value))
27+
}
28+
29+
fn round(value: f64) -> f64 {
30+
(value * 100.0).round() / 100.0
31+
}
32+
33+
#[cfg(test)]
34+
mod tests {
35+
use super::*;
36+
37+
macro_rules! test_present_value {
38+
($($name:ident: $inputs:expr,)*) => {
39+
$(
40+
#[test]
41+
fn $name() {
42+
let ((discount_rate,cash_flows), expected) = $inputs;
43+
assert_eq!(present_value(discount_rate,cash_flows).unwrap(), expected);
44+
}
45+
)*
46+
}
47+
}
48+
49+
macro_rules! test_present_value_Err {
50+
($($name:ident: $inputs:expr,)*) => {
51+
$(
52+
#[test]
53+
fn $name() {
54+
let ((discount_rate,cash_flows), expected) = $inputs;
55+
assert_eq!(present_value(discount_rate,cash_flows).unwrap_err(), expected);
56+
}
57+
)*
58+
}
59+
}
60+
61+
macro_rules! test_round {
62+
($($name:ident: $inputs:expr,)*) => {
63+
$(
64+
#[test]
65+
fn $name() {
66+
let (input, expected) = $inputs;
67+
assert_eq!(round(input), expected);
68+
}
69+
)*
70+
}
71+
}
72+
73+
test_present_value! {
74+
general_inputs1:((0.13, vec![10.0, 20.70, -293.0, 297.0]),4.69),
75+
general_inputs2:((0.07, vec![-109129.39, 30923.23, 15098.93, 29734.0, 39.0]),-42739.63),
76+
general_inputs3:((0.07, vec![109129.39, 30923.23, 15098.93, 29734.0, 39.0]), 175519.15),
77+
zero_input:((0.0, vec![109129.39, 30923.23, 15098.93, 29734.0, 39.0]), 184924.55),
78+
79+
}
80+
81+
test_present_value_Err! {
82+
negative_discount_rate:((-1.0, vec![10.0, 20.70, -293.0, 297.0]), PresentValueError::NegetiveDiscount),
83+
empty_cash_flow:((1.0, vec![]), PresentValueError::EmptyCashFlow),
84+
85+
}
86+
test_round! {
87+
test1:(0.55434, 0.55),
88+
test2:(10.453, 10.45),
89+
test3:(1111_f64, 1111_f64),
90+
}
91+
}

src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ pub mod compression;
88
pub mod conversions;
99
pub mod data_structures;
1010
pub mod dynamic_programming;
11+
pub mod financial;
1112
pub mod general;
1213
pub mod geometry;
1314
pub mod graph;

src/string/palindrome.rs

Lines changed: 59 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,74 @@
1+
//! A module for checking if a given string is a palindrome.
2+
3+
/// Checks if the given string is a palindrome.
4+
///
5+
/// A palindrome is a sequence that reads the same backward as forward.
6+
/// This function ignores non-alphanumeric characters and is case-insensitive.
7+
///
8+
/// # Arguments
9+
///
10+
/// * `s` - A string slice that represents the input to be checked.
11+
///
12+
/// # Returns
13+
///
14+
/// * `true` if the string is a palindrome; otherwise, `false`.
115
pub fn is_palindrome(s: &str) -> bool {
2-
let mut chars = s.chars();
16+
let mut chars = s
17+
.chars()
18+
.filter(|c| c.is_alphanumeric())
19+
.map(|c| c.to_ascii_lowercase());
20+
321
while let (Some(c1), Some(c2)) = (chars.next(), chars.next_back()) {
422
if c1 != c2 {
523
return false;
624
}
725
}
26+
827
true
928
}
1029

1130
#[cfg(test)]
1231
mod tests {
1332
use super::*;
1433

15-
#[test]
16-
fn palindromes() {
17-
assert!(is_palindrome("abcba"));
18-
assert!(is_palindrome("abba"));
19-
assert!(is_palindrome("a"));
20-
assert!(is_palindrome("arcra"));
21-
assert!(!is_palindrome("abcde"));
22-
assert!(!is_palindrome("aaaabbbb"));
34+
macro_rules! palindrome_tests {
35+
($($name:ident: $inputs:expr,)*) => {
36+
$(
37+
#[test]
38+
fn $name() {
39+
let (input, expected) = $inputs;
40+
assert_eq!(is_palindrome(input), expected);
41+
}
42+
)*
43+
}
44+
}
45+
46+
palindrome_tests! {
47+
odd_palindrome: ("madam", true),
48+
even_palindrome: ("deified", true),
49+
single_character_palindrome: ("x", true),
50+
single_word_palindrome: ("eye", true),
51+
case_insensitive_palindrome: ("RaceCar", true),
52+
mixed_case_and_punctuation_palindrome: ("A man, a plan, a canal, Panama!", true),
53+
mixed_case_and_space_palindrome: ("No 'x' in Nixon", true),
54+
empty_string: ("", true),
55+
pompeii_palindrome: ("Roma-Olima-Milo-Amor", true),
56+
napoleon_palindrome: ("Able was I ere I saw Elba", true),
57+
john_taylor_palindrome: ("Lewd did I live, & evil I did dwel", true),
58+
well_know_english_palindrome: ("Never odd or even", true),
59+
palindromic_phrase: ("Rats live on no evil star", true),
60+
names_palindrome: ("Hannah", true),
61+
prime_minister_of_cambodia: ("Lon Nol", true),
62+
japanese_novelist_and_manga_writer: ("Nisio Isin", true),
63+
actor: ("Robert Trebor", true),
64+
rock_vocalist: ("Ola Salo", true),
65+
pokemon_species: ("Girafarig", true),
66+
lychrel_num_56: ("121", true),
67+
universal_palindrome_date: ("02/02/2020", true),
68+
french_palindrome: ("une Slave valse nu", true),
69+
finnish_palindrome: ("saippuakivikauppias", true),
70+
non_palindrome_simple: ("hello", false),
71+
non_palindrome_with_punctuation: ("hello!", false),
72+
non_palindrome_mixed_case: ("Hello, World", false),
2373
}
2474
}

0 commit comments

Comments
 (0)