-
Notifications
You must be signed in to change notification settings - Fork 4.7k
Expand file tree
/
Copy pathchinese_remainder_theorem.py
More file actions
72 lines (57 loc) · 2.06 KB
/
chinese_remainder_theorem.py
File metadata and controls
72 lines (57 loc) · 2.06 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
"""
Chinese Remainder Theorem
Solves a system of simultaneous congruences using the Chinese Remainder
Theorem. Given pairwise coprime moduli, finds the smallest positive integer
satisfying all congruences.
Reference: https://en.wikipedia.org/wiki/Chinese_remainder_theorem
Complexity:
Time: O(n * m) where n is the number of equations and m is the solution
Space: O(1)
"""
from __future__ import annotations
from algorithms.math.gcd import gcd
def solve_chinese_remainder(nums: list[int], rems: list[int]) -> int:
"""Find the smallest x satisfying x % nums[i] == rems[i] for all i.
Args:
nums: List of pairwise coprime moduli, each greater than 1.
rems: List of remainders corresponding to each modulus.
Returns:
The smallest positive integer satisfying all congruences.
Raises:
Exception: If inputs are invalid or moduli are not pairwise coprime.
Examples:
>>> solve_chinese_remainder([3, 7, 10], [2, 3, 3])
143
"""
if not len(nums) == len(rems):
raise Exception("nums and rems should have equal length")
if not len(nums) > 0:
raise Exception("Lists nums and rems need to contain at least one element")
for num in nums:
if not num > 1:
raise Exception("All numbers in nums needs to be > 1")
if not _check_coprime(nums):
raise Exception("All pairs of numbers in nums are not coprime")
k = len(nums)
x = 1
while True:
i = 0
while i < k:
if x % nums[i] != rems[i]:
break
i += 1
if i == k:
return x
x += 1
def _check_coprime(list_to_check: list[int]) -> bool:
"""Check whether all pairs of numbers in the list are coprime.
Args:
list_to_check: List of integers to check for pairwise coprimality.
Returns:
True if all pairs are coprime, False otherwise.
"""
for ind, num in enumerate(list_to_check):
for num2 in list_to_check[ind + 1 :]:
if gcd(num, num2) != 1:
return False
return True