Skip to content

Commit 0f0b468

Browse files
authored
Add nth Fibonacci number modulo m (TheAlgorithms#514)
1 parent c1b82b8 commit 0f0b468

File tree

2 files changed

+101
-0
lines changed

2 files changed

+101
-0
lines changed

src/dynamic_programming/fibonacci.rs

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,13 +180,84 @@ fn matrix_multiply(multiplier: &[Vec<u128>], multiplicand: &[Vec<u128>]) -> Vec<
180180
result
181181
}
182182

183+
/// nth_fibonacci_number_modulo_m(n, m) returns the nth fibonacci number modulo the specified m
184+
/// i.e. F(n) % m
185+
pub fn nth_fibonacci_number_modulo_m(n: i64, m: i64) -> i128 {
186+
let (length, pisano_sequence) = get_pisano_sequence_and_period(m);
187+
188+
let remainder = n % length as i64;
189+
pisano_sequence.get(remainder as usize).unwrap().to_owned()
190+
}
191+
192+
/// get_pisano_sequence_and_period(m) returns the Pisano Sequence and period for the specified integer m.
193+
/// The pisano period is the period with which the sequence of Fibonacci numbers taken modulo m repeats.
194+
/// The pisano sequence is the numbers in pisano period.
195+
fn get_pisano_sequence_and_period(m: i64) -> (i128, Vec<i128>) {
196+
let mut a = 0;
197+
let mut b = 1;
198+
let mut lenght: i128 = 0;
199+
let mut pisano_sequence: Vec<i128> = vec![a, b];
200+
201+
// Iterating through all the fib numbers to get the sequence
202+
for _i in 0..(m * m) + 1 {
203+
let c = (a + b) % m as i128;
204+
205+
// adding number into the sequence
206+
pisano_sequence.push(c);
207+
208+
a = b;
209+
b = c;
210+
211+
if a == 0 && b == 1 {
212+
// Remove the last two elements from the sequence
213+
// This is a less elegant way to do it.
214+
pisano_sequence.pop();
215+
pisano_sequence.pop();
216+
lenght = pisano_sequence.len() as i128;
217+
break;
218+
}
219+
}
220+
221+
(lenght, pisano_sequence)
222+
}
223+
224+
/// last_digit_of_the_sum_of_nth_fibonacci_number(n) returns the last digit of the sum of n fibonacci numbers.
225+
/// The function uses the definition of Fibonacci where:
226+
/// F(0) = 0, F(1) = 1 and F(n+1) = F(n) + F(n-1) for n > 2
227+
///
228+
/// The sum of the Fibonacci numbers are:
229+
/// F(0) + F(1) + F(2) + ... + F(n)
230+
pub fn last_digit_of_the_sum_of_nth_fibonacci_number(n: i64) -> i64 {
231+
if n < 2 {
232+
return n;
233+
}
234+
235+
// the pisano period of mod 10 is 60
236+
let n = ((n + 2) % 60) as usize;
237+
let mut fib = vec![0; n + 1];
238+
fib[0] = 0;
239+
fib[1] = 1;
240+
241+
for i in 2..=n {
242+
fib[i] = (fib[i - 1] % 10 + fib[i - 2] % 10) % 10;
243+
}
244+
245+
if fib[n] == 0 {
246+
return 9;
247+
}
248+
249+
fib[n] % 10 - 1
250+
}
251+
183252
#[cfg(test)]
184253
mod tests {
185254
use super::classical_fibonacci;
186255
use super::fibonacci;
256+
use super::last_digit_of_the_sum_of_nth_fibonacci_number;
187257
use super::logarithmic_fibonacci;
188258
use super::matrix_fibonacci;
189259
use super::memoized_fibonacci;
260+
use super::nth_fibonacci_number_modulo_m;
190261
use super::recursive_fibonacci;
191262

192263
#[test]
@@ -326,4 +397,32 @@ mod tests {
326397
127127879743834334146972278486287885163
327398
);
328399
}
400+
401+
#[test]
402+
fn test_nth_fibonacci_number_modulo_m() {
403+
assert_eq!(nth_fibonacci_number_modulo_m(5, 10), 5);
404+
assert_eq!(nth_fibonacci_number_modulo_m(10, 7), 6);
405+
assert_eq!(nth_fibonacci_number_modulo_m(20, 100), 65);
406+
assert_eq!(nth_fibonacci_number_modulo_m(1, 5), 1);
407+
assert_eq!(nth_fibonacci_number_modulo_m(0, 15), 0);
408+
assert_eq!(nth_fibonacci_number_modulo_m(50, 1000), 25);
409+
assert_eq!(nth_fibonacci_number_modulo_m(100, 37), 7);
410+
assert_eq!(nth_fibonacci_number_modulo_m(15, 2), 0);
411+
assert_eq!(nth_fibonacci_number_modulo_m(8, 1_000_000), 21);
412+
assert_eq!(nth_fibonacci_number_modulo_m(1000, 997), 996);
413+
assert_eq!(nth_fibonacci_number_modulo_m(200, 123), 0);
414+
}
415+
416+
#[test]
417+
fn test_last_digit_of_the_sum_of_nth_fibonacci_number() {
418+
assert_eq!(last_digit_of_the_sum_of_nth_fibonacci_number(0), 0);
419+
assert_eq!(last_digit_of_the_sum_of_nth_fibonacci_number(1), 1);
420+
assert_eq!(last_digit_of_the_sum_of_nth_fibonacci_number(2), 2);
421+
assert_eq!(last_digit_of_the_sum_of_nth_fibonacci_number(3), 4);
422+
assert_eq!(last_digit_of_the_sum_of_nth_fibonacci_number(4), 7);
423+
assert_eq!(last_digit_of_the_sum_of_nth_fibonacci_number(5), 2);
424+
assert_eq!(last_digit_of_the_sum_of_nth_fibonacci_number(25), 7);
425+
assert_eq!(last_digit_of_the_sum_of_nth_fibonacci_number(50), 8);
426+
assert_eq!(last_digit_of_the_sum_of_nth_fibonacci_number(100), 5);
427+
}
329428
}

src/dynamic_programming/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,11 @@ pub use self::coin_change::coin_change;
1919
pub use self::egg_dropping::egg_drop;
2020
pub use self::fibonacci::classical_fibonacci;
2121
pub use self::fibonacci::fibonacci;
22+
pub use self::fibonacci::last_digit_of_the_sum_of_nth_fibonacci_number;
2223
pub use self::fibonacci::logarithmic_fibonacci;
2324
pub use self::fibonacci::matrix_fibonacci;
2425
pub use self::fibonacci::memoized_fibonacci;
26+
pub use self::fibonacci::nth_fibonacci_number_modulo_m;
2527
pub use self::fibonacci::recursive_fibonacci;
2628
pub use self::fractional_knapsack::fractional_knapsack;
2729
pub use self::is_subsequence::is_subsequence;

0 commit comments

Comments
 (0)