Skip to content

Commit 46b3405

Browse files
authored
Merge branch 'master' into ref/ds/segment_tree
2 parents 99de1b4 + 5151982 commit 46b3405

File tree

7 files changed

+296
-42
lines changed

7 files changed

+296
-42
lines changed

DIRECTORY.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,10 @@
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)
59+
* [Rgb Cmyk Conversion](https://github.com/TheAlgorithms/Rust/blob/master/src/conversions/rgb_cmyk_conversion.rs)
5860
* Data Structures
5961
* [Avl Tree](https://github.com/TheAlgorithms/Rust/blob/master/src/data_structures/avl_tree.rs)
6062
* [B Tree](https://github.com/TheAlgorithms/Rust/blob/master/src/data_structures/b_tree.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: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,17 @@ 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;
10+
mod rgb_cmyk_conversion;
911
pub use self::binary_to_decimal::binary_to_decimal;
1012
pub use self::binary_to_hexadecimal::binary_to_hexadecimal;
1113
pub use self::decimal_to_binary::decimal_to_binary;
1214
pub use self::decimal_to_hexadecimal::decimal_to_hexadecimal;
1315
pub use self::hexadecimal_to_binary::hexadecimal_to_binary;
1416
pub use self::hexadecimal_to_decimal::hexadecimal_to_decimal;
17+
pub use self::length_conversion::length_conversion;
1518
pub use self::octal_to_binary::octal_to_binary;
1619
pub use self::octal_to_decimal::octal_to_decimal;
20+
pub use self::rgb_cmyk_conversion::rgb_to_cmyk;
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
/// Author : https://github.com/ali77gh\
2+
/// References:\
3+
/// RGB: https://en.wikipedia.org/wiki/RGB_color_model\
4+
/// CMYK: https://en.wikipedia.org/wiki/CMYK_color_model\
5+
6+
/// This function Converts RGB to CMYK format
7+
///
8+
/// ### Params
9+
/// * `r` - red
10+
/// * `g` - green
11+
/// * `b` - blue
12+
///
13+
/// ### Returns
14+
/// (C, M, Y, K)
15+
pub fn rgb_to_cmyk(rgb: (u8, u8, u8)) -> (u8, u8, u8, u8) {
16+
// Safety: no need to check if input is positive and less than 255 because it's u8
17+
18+
// change scale from [0,255] to [0,1]
19+
let (r, g, b) = (
20+
rgb.0 as f64 / 255f64,
21+
rgb.1 as f64 / 255f64,
22+
rgb.2 as f64 / 255f64,
23+
);
24+
25+
match 1f64 - r.max(g).max(b) {
26+
1f64 => (0, 0, 0, 100), // pure black
27+
k => (
28+
(100f64 * (1f64 - r - k) / (1f64 - k)) as u8, // c
29+
(100f64 * (1f64 - g - k) / (1f64 - k)) as u8, // m
30+
(100f64 * (1f64 - b - k) / (1f64 - k)) as u8, // y
31+
(100f64 * k) as u8, // k
32+
),
33+
}
34+
}
35+
36+
#[cfg(test)]
37+
mod tests {
38+
use super::*;
39+
40+
macro_rules! test_rgb_to_cmyk {
41+
($($name:ident: $tc:expr,)*) => {
42+
$(
43+
#[test]
44+
fn $name() {
45+
let (rgb, cmyk) = $tc;
46+
assert_eq!(rgb_to_cmyk(rgb), cmyk);
47+
}
48+
)*
49+
}
50+
}
51+
52+
test_rgb_to_cmyk! {
53+
white: ((255, 255, 255), (0, 0, 0, 0)),
54+
gray: ((128, 128, 128), (0, 0, 0, 49)),
55+
black: ((0, 0, 0), (0, 0, 0, 100)),
56+
red: ((255, 0, 0), (0, 100, 100, 0)),
57+
green: ((0, 255, 0), (100, 0, 100, 0)),
58+
blue: ((0, 0, 255), (100, 100, 0, 0)),
59+
}
60+
}

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);

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)