Skip to content

Commit efbe4af

Browse files
authored
Merge branch 'master' into rgb_cmyk_conversion
2 parents 126f893 + c906255 commit efbe4af

File tree

12 files changed

+546
-111
lines changed

12 files changed

+546
-111
lines changed

DIRECTORY.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@
5353
* [Decimal To Hexadecimal](https://github.com/TheAlgorithms/Rust/blob/master/src/conversions/decimal_to_hexadecimal.rs)
5454
* [Hexadecimal To Binary](https://github.com/TheAlgorithms/Rust/blob/master/src/conversions/hexadecimal_to_binary.rs)
5555
* [Hexadecimal To Decimal](https://github.com/TheAlgorithms/Rust/blob/master/src/conversions/hexadecimal_to_decimal.rs)
56+
* [Length Conversion](https://github.com/TheAlgorithms/Rust/blob/master/src/conversions/length_conversion.rs)
5657
* [Octal To Binary](https://github.com/TheAlgorithms/Rust/blob/master/src/conversions/octal_to_binary.rs)
5758
* [Octal To Decimal](https://github.com/TheAlgorithms/Rust/blob/master/src/conversions/octal_to_decimal.rs)
5859
* [RGB to CMYK](https://github.com/TheAlgorithms/Rust/blob/master/src/conversions/rgb_cmyk_conversion.rs)
@@ -157,6 +158,7 @@
157158
* [Cholesky](https://github.com/TheAlgorithms/Rust/blob/master/src/machine_learning/cholesky.rs)
158159
* [K Means](https://github.com/TheAlgorithms/Rust/blob/master/src/machine_learning/k_means.rs)
159160
* [Linear Regression](https://github.com/TheAlgorithms/Rust/blob/master/src/machine_learning/linear_regression.rs)
161+
* [Logistic Regression](https://github.com/TheAlgorithms/Rust/blob/master/src/machine_learning/logistic_regression.rs)
160162
* Loss Function
161163
* [Average Margin Ranking Loss](https://github.com/TheAlgorithms/Rust/blob/master/src/machine_learning/loss_function/average_margin_ranking_loss.rs)
162164
* [Hinge Loss](https://github.com/TheAlgorithms/Rust/blob/master/src/machine_learning/loss_function/hinge_loss.rs)
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
/// Author : https://github.com/ali77gh
2+
/// Conversion of length units.
3+
///
4+
/// Available Units:
5+
/// -> Wikipedia reference: https://en.wikipedia.org/wiki/Millimeter
6+
/// -> Wikipedia reference: https://en.wikipedia.org/wiki/Centimeter
7+
/// -> Wikipedia reference: https://en.wikipedia.org/wiki/Meter
8+
/// -> Wikipedia reference: https://en.wikipedia.org/wiki/Kilometer
9+
/// -> Wikipedia reference: https://en.wikipedia.org/wiki/Inch
10+
/// -> Wikipedia reference: https://en.wikipedia.org/wiki/Foot
11+
/// -> Wikipedia reference: https://en.wikipedia.org/wiki/Yard
12+
/// -> Wikipedia reference: https://en.wikipedia.org/wiki/Mile
13+
14+
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
15+
pub enum LengthUnit {
16+
Millimeter,
17+
Centimeter,
18+
Meter,
19+
Kilometer,
20+
Inch,
21+
Foot,
22+
Yard,
23+
Mile,
24+
}
25+
26+
fn unit_to_meter_multiplier(from: LengthUnit) -> f64 {
27+
match from {
28+
LengthUnit::Millimeter => 0.001,
29+
LengthUnit::Centimeter => 0.01,
30+
LengthUnit::Meter => 1.0,
31+
LengthUnit::Kilometer => 1000.0,
32+
LengthUnit::Inch => 0.0254,
33+
LengthUnit::Foot => 0.3048,
34+
LengthUnit::Yard => 0.9144,
35+
LengthUnit::Mile => 1609.34,
36+
}
37+
}
38+
39+
fn unit_to_meter(input: f64, from: LengthUnit) -> f64 {
40+
input * unit_to_meter_multiplier(from)
41+
}
42+
43+
fn meter_to_unit(input: f64, to: LengthUnit) -> f64 {
44+
input / unit_to_meter_multiplier(to)
45+
}
46+
47+
/// This function will convert a value in unit of [from] to value in unit of [to]
48+
/// by first converting it to meter and than convert it to destination unit
49+
pub fn length_conversion(input: f64, from: LengthUnit, to: LengthUnit) -> f64 {
50+
meter_to_unit(unit_to_meter(input, from), to)
51+
}
52+
53+
#[cfg(test)]
54+
mod length_conversion_tests {
55+
use std::collections::HashMap;
56+
57+
use super::LengthUnit::*;
58+
use super::*;
59+
60+
#[test]
61+
fn zero_to_zero() {
62+
let units = vec![
63+
Millimeter, Centimeter, Meter, Kilometer, Inch, Foot, Yard, Mile,
64+
];
65+
66+
for u1 in units.clone() {
67+
for u2 in units.clone() {
68+
assert_eq!(length_conversion(0f64, u1, u2), 0f64);
69+
}
70+
}
71+
}
72+
73+
#[test]
74+
fn length_of_one_meter() {
75+
let meter_in_different_units = HashMap::from([
76+
(Millimeter, 1000f64),
77+
(Centimeter, 100f64),
78+
(Kilometer, 0.001f64),
79+
(Inch, 39.37007874015748f64),
80+
(Foot, 3.280839895013123f64),
81+
(Yard, 1.0936132983377078f64),
82+
(Mile, 0.0006213727366498068f64),
83+
]);
84+
for (input_unit, input_value) in &meter_in_different_units {
85+
for (target_unit, target_value) in &meter_in_different_units {
86+
assert!(
87+
num_traits::abs(
88+
length_conversion(*input_value, *input_unit, *target_unit) - *target_value
89+
) < 0.0000001
90+
);
91+
}
92+
}
93+
}
94+
}

src/conversions/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ mod decimal_to_binary;
44
mod decimal_to_hexadecimal;
55
mod hexadecimal_to_binary;
66
mod hexadecimal_to_decimal;
7+
mod length_conversion;
78
mod octal_to_binary;
89
mod octal_to_decimal;
910
mod rgb_cmyk_conversion;
@@ -13,6 +14,7 @@ pub use self::decimal_to_binary::decimal_to_binary;
1314
pub use self::decimal_to_hexadecimal::decimal_to_hexadecimal;
1415
pub use self::hexadecimal_to_binary::hexadecimal_to_binary;
1516
pub use self::hexadecimal_to_decimal::hexadecimal_to_decimal;
17+
pub use self::length_conversion::length_conversion;
1618
pub use self::octal_to_binary::octal_to_binary;
1719
pub use self::octal_to_decimal::octal_to_decimal;
1820
pub use self::rgb_cmyk_conversion::rgb_to_cmyk;

src/dynamic_programming/fibonacci.rs

Lines changed: 51 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ fn matrix_multiply(multiplier: &[Vec<u128>], multiplicand: &[Vec<u128>]) -> Vec<
158158
// of columns as the multiplicand has rows.
159159
let mut result: Vec<Vec<u128>> = vec![];
160160
let mut temp;
161-
// Using variable to compare lenghts of rows in multiplicand later
161+
// Using variable to compare lengths of rows in multiplicand later
162162
let row_right_length = multiplicand[0].len();
163163
for row_left in 0..multiplier.len() {
164164
if multiplier[row_left].len() != multiplicand.len() {
@@ -180,6 +180,33 @@ fn matrix_multiply(multiplier: &[Vec<u128>], multiplicand: &[Vec<u128>]) -> Vec<
180180
result
181181
}
182182

183+
/// Binary lifting fibonacci
184+
///
185+
/// Following properties of F(n) could be deduced from the matrix formula above:
186+
///
187+
/// F(2n) = F(n) * (2F(n+1) - F(n))
188+
/// F(2n+1) = F(n+1)^2 + F(n)^2
189+
///
190+
/// Therefore F(n) and F(n+1) can be derived from F(n>>1) and F(n>>1 + 1), which
191+
/// has a smaller constant in both time and space compared to matrix fibonacci.
192+
pub fn binary_lifting_fibonacci(n: u32) -> u128 {
193+
// the state always stores F(k), F(k+1) for some k, initially F(0), F(1)
194+
let mut state = (0u128, 1u128);
195+
196+
for i in (0..u32::BITS - n.leading_zeros()).rev() {
197+
// compute F(2k), F(2k+1) from F(k), F(k+1)
198+
state = (
199+
state.0 * (2 * state.1 - state.0),
200+
state.0 * state.0 + state.1 * state.1,
201+
);
202+
if n & (1 << i) != 0 {
203+
state = (state.1, state.0 + state.1);
204+
}
205+
}
206+
207+
state.0
208+
}
209+
183210
/// nth_fibonacci_number_modulo_m(n, m) returns the nth fibonacci number modulo the specified m
184211
/// i.e. F(n) % m
185212
pub fn nth_fibonacci_number_modulo_m(n: i64, m: i64) -> i128 {
@@ -195,7 +222,7 @@ pub fn nth_fibonacci_number_modulo_m(n: i64, m: i64) -> i128 {
195222
fn get_pisano_sequence_and_period(m: i64) -> (i128, Vec<i128>) {
196223
let mut a = 0;
197224
let mut b = 1;
198-
let mut lenght: i128 = 0;
225+
let mut length: i128 = 0;
199226
let mut pisano_sequence: Vec<i128> = vec![a, b];
200227

201228
// Iterating through all the fib numbers to get the sequence
@@ -213,12 +240,12 @@ fn get_pisano_sequence_and_period(m: i64) -> (i128, Vec<i128>) {
213240
// This is a less elegant way to do it.
214241
pisano_sequence.pop();
215242
pisano_sequence.pop();
216-
lenght = pisano_sequence.len() as i128;
243+
length = pisano_sequence.len() as i128;
217244
break;
218245
}
219246
}
220247

221-
(lenght, pisano_sequence)
248+
(length, pisano_sequence)
222249
}
223250

224251
/// last_digit_of_the_sum_of_nth_fibonacci_number(n) returns the last digit of the sum of n fibonacci numbers.
@@ -251,6 +278,7 @@ pub fn last_digit_of_the_sum_of_nth_fibonacci_number(n: i64) -> i64 {
251278

252279
#[cfg(test)]
253280
mod tests {
281+
use super::binary_lifting_fibonacci;
254282
use super::classical_fibonacci;
255283
use super::fibonacci;
256284
use super::last_digit_of_the_sum_of_nth_fibonacci_number;
@@ -328,7 +356,7 @@ mod tests {
328356
}
329357

330358
#[test]
331-
/// Check that the itterative and recursive fibonacci
359+
/// Check that the iterative and recursive fibonacci
332360
/// produce the same value. Both are combinatorial ( F(0) = F(1) = 1 )
333361
fn test_iterative_and_recursive_equivalence() {
334362
assert_eq!(fibonacci(0), recursive_fibonacci(0));
@@ -398,6 +426,24 @@ mod tests {
398426
);
399427
}
400428

429+
#[test]
430+
fn test_binary_lifting_fibonacci() {
431+
assert_eq!(binary_lifting_fibonacci(0), 0);
432+
assert_eq!(binary_lifting_fibonacci(1), 1);
433+
assert_eq!(binary_lifting_fibonacci(2), 1);
434+
assert_eq!(binary_lifting_fibonacci(3), 2);
435+
assert_eq!(binary_lifting_fibonacci(4), 3);
436+
assert_eq!(binary_lifting_fibonacci(5), 5);
437+
assert_eq!(binary_lifting_fibonacci(10), 55);
438+
assert_eq!(binary_lifting_fibonacci(20), 6765);
439+
assert_eq!(binary_lifting_fibonacci(21), 10946);
440+
assert_eq!(binary_lifting_fibonacci(100), 354224848179261915075);
441+
assert_eq!(
442+
binary_lifting_fibonacci(184),
443+
127127879743834334146972278486287885163
444+
);
445+
}
446+
401447
#[test]
402448
fn test_nth_fibonacci_number_modulo_m() {
403449
assert_eq!(nth_fibonacci_number_modulo_m(5, 10), 5);
Lines changed: 58 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,71 @@
1-
// Given two strings str1 and str2, return true if str1 is a subsequence of str2, or false otherwise.
2-
// A subsequence of a string is a new string that is formed from the original string
3-
// by deleting some (can be none) of the characters without disturbing the relative
4-
// positions of the remaining characters.
5-
// (i.e., "ace" is a subsequence of "abcde" while "aec" is not).
6-
pub fn is_subsequence(str1: &str, str2: &str) -> bool {
7-
let mut it1 = 0;
8-
let mut it2 = 0;
1+
//! A module for checking if one string is a subsequence of another string.
2+
//!
3+
//! A subsequence is formed by deleting some (can be none) of the characters
4+
//! from the original string without disturbing the relative positions of the
5+
//! remaining characters. This module provides a function to determine if
6+
//! a given string is a subsequence of another string.
97
10-
let byte1 = str1.as_bytes();
11-
let byte2 = str2.as_bytes();
8+
/// Checks if `sub` is a subsequence of `main`.
9+
///
10+
/// # Arguments
11+
///
12+
/// * `sub` - A string slice that may be a subsequence.
13+
/// * `main` - A string slice that is checked against.
14+
///
15+
/// # Returns
16+
///
17+
/// Returns `true` if `sub` is a subsequence of `main`, otherwise returns `false`.
18+
pub fn is_subsequence(sub: &str, main: &str) -> bool {
19+
let mut sub_iter = sub.chars().peekable();
20+
let mut main_iter = main.chars();
1221

13-
while it1 < str1.len() && it2 < str2.len() {
14-
if byte1[it1] == byte2[it2] {
15-
it1 += 1;
22+
while let Some(&sub_char) = sub_iter.peek() {
23+
match main_iter.next() {
24+
Some(main_char) if main_char == sub_char => {
25+
sub_iter.next();
26+
}
27+
None => return false,
28+
_ => {}
1629
}
17-
18-
it2 += 1;
1930
}
2031

21-
it1 == str1.len()
32+
true
2233
}
2334

2435
#[cfg(test)]
2536
mod tests {
2637
use super::*;
2738

28-
#[test]
29-
fn test() {
30-
assert!(is_subsequence("abc", "ahbgdc"));
31-
assert!(!is_subsequence("axc", "ahbgdc"));
39+
macro_rules! subsequence_tests {
40+
($($name:ident: $test_case:expr,)*) => {
41+
$(
42+
#[test]
43+
fn $name() {
44+
let (sub, main, expected) = $test_case;
45+
assert_eq!(is_subsequence(sub, main), expected);
46+
}
47+
)*
48+
};
49+
}
50+
51+
subsequence_tests! {
52+
test_empty_subsequence: ("", "ahbgdc", true),
53+
test_empty_strings: ("", "", true),
54+
test_non_empty_sub_empty_main: ("abc", "", false),
55+
test_subsequence_found: ("abc", "ahbgdc", true),
56+
test_subsequence_not_found: ("axc", "ahbgdc", false),
57+
test_longer_sub: ("abcd", "abc", false),
58+
test_single_character_match: ("a", "ahbgdc", true),
59+
test_single_character_not_match: ("x", "ahbgdc", false),
60+
test_subsequence_at_start: ("abc", "abchello", true),
61+
test_subsequence_at_end: ("cde", "abcde", true),
62+
test_same_characters: ("aaa", "aaaaa", true),
63+
test_interspersed_subsequence: ("ace", "abcde", true),
64+
test_different_chars_in_subsequence: ("aceg", "abcdef", false),
65+
test_single_character_in_main_not_match: ("a", "b", false),
66+
test_single_character_in_main_match: ("b", "b", true),
67+
test_subsequence_with_special_chars: ("a1!c", "a1!bcd", true),
68+
test_case_sensitive: ("aBc", "abc", false),
69+
test_subsequence_with_whitespace: ("hello world", "h e l l o w o r l d", true),
3270
}
3371
}

src/dynamic_programming/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ mod word_break;
2020

2121
pub use self::coin_change::coin_change;
2222
pub use self::egg_dropping::egg_drop;
23+
pub use self::fibonacci::binary_lifting_fibonacci;
2324
pub use self::fibonacci::classical_fibonacci;
2425
pub use self::fibonacci::fibonacci;
2526
pub use self::fibonacci::last_digit_of_the_sum_of_nth_fibonacci_number;

0 commit comments

Comments
 (0)