Skip to content

Commit ccaf0fd

Browse files
authored
Merge branch 'master' into ref/string/shorted_palindrome
2 parents 1315034 + 9cb06fc commit ccaf0fd

File tree

5 files changed

+149
-5
lines changed

5 files changed

+149
-5
lines changed

DIRECTORY.md

Lines changed: 1 addition & 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
* Data Structures
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
pub use self::binary_to_decimal::binary_to_decimal;
@@ -12,5 +13,6 @@ pub use self::decimal_to_binary::decimal_to_binary;
1213
pub use self::decimal_to_hexadecimal::decimal_to_hexadecimal;
1314
pub use self::hexadecimal_to_binary::hexadecimal_to_binary;
1415
pub use self::hexadecimal_to_decimal::hexadecimal_to_decimal;
16+
pub use self::length_conversion::length_conversion;
1517
pub use self::octal_to_binary::octal_to_binary;
1618
pub use self::octal_to_decimal::octal_to_decimal;

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)