Skip to content

Commit d26cbb1

Browse files
GentBinakuGBinaku
andauthored
Add Chinese Remainder Theorem (TheAlgorithms#378)
Co-authored-by: Gent Binaku <[email protected]>
1 parent 2ec70c2 commit d26cbb1

File tree

2 files changed

+37
-0
lines changed

2 files changed

+37
-0
lines changed
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
use super::extended_euclidean_algorithm;
2+
3+
fn mod_inv(x: i32, n: i32) -> Option<i32> {
4+
let (g, x, _) = extended_euclidean_algorithm(x, n);
5+
if g == 1 {
6+
Some((x % n + n) % n)
7+
} else {
8+
None
9+
}
10+
}
11+
12+
pub fn chinese_remainder_theorem(residues: &[i32], modulli: &[i32]) -> Option<i32> {
13+
let prod = modulli.iter().product::<i32>();
14+
15+
let mut sum = 0;
16+
17+
for (&residue, &modulus) in residues.iter().zip(modulli) {
18+
let p = prod / modulus;
19+
sum += residue * mod_inv(p, modulus)? * p
20+
}
21+
Some(sum % prod)
22+
}
23+
24+
#[cfg(test)]
25+
mod tests {
26+
use super::*;
27+
28+
#[test]
29+
fn basic() {
30+
assert_eq!(chinese_remainder_theorem(&[3, 5, 7], &[2, 3, 1]), Some(5));
31+
assert_eq!(chinese_remainder_theorem(&[1, 4, 6], &[3, 5, 7]), Some(34));
32+
assert_eq!(chinese_remainder_theorem(&[1, 4, 6], &[1, 2, 0]), None);
33+
assert_eq!(chinese_remainder_theorem(&[2, 5, 7], &[6, 9, 15]), None);
34+
}
35+
}

src/math/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
mod amicable_numbers;
22
mod armstrong_number;
33
mod baby_step_giant_step;
4+
mod chinese_remainder_theorem;
45
mod extended_euclidean_algorithm;
56
mod fast_fourier_transform;
67
mod fast_power;
@@ -33,6 +34,7 @@ mod zellers_congruence_algorithm;
3334
pub use self::amicable_numbers::amicable_pairs_under_n;
3435
pub use self::armstrong_number::is_armstrong_number;
3536
pub use self::baby_step_giant_step::baby_step_giant_step;
37+
pub use self::chinese_remainder_theorem::chinese_remainder_theorem;
3638
pub use self::extended_euclidean_algorithm::extended_euclidean_algorithm;
3739
pub use self::fast_fourier_transform::{
3840
fast_fourier_transform, fast_fourier_transform_input_permutation,

0 commit comments

Comments
 (0)