From cecc4492668655c7eb1bd65cbfb09921b27ddc46 Mon Sep 17 00:00:00 2001 From: suprhulk Date: Wed, 16 Oct 2024 17:20:37 +0530 Subject: [PATCH 01/10] Implemented chinese remainder theorem with test file --- .../maths/ChineseRemainderTheorem.java | 75 +++++++++++++++++++ .../maths/ChineseRemainderTheoremTest.java | 75 +++++++++++++++++++ 2 files changed, 150 insertions(+) create mode 100644 src/main/java/com/thealgorithms/maths/ChineseRemainderTheorem.java create mode 100644 src/test/java/com/thealgorithms/maths/ChineseRemainderTheoremTest.java diff --git a/src/main/java/com/thealgorithms/maths/ChineseRemainderTheorem.java b/src/main/java/com/thealgorithms/maths/ChineseRemainderTheorem.java new file mode 100644 index 000000000000..a290a92cd453 --- /dev/null +++ b/src/main/java/com/thealgorithms/maths/ChineseRemainderTheorem.java @@ -0,0 +1,75 @@ +package com.thealgorithms.maths; + +import java.util.List; + +/** + * @brief Implementation of the Chinese Remainder Theorem (CRT) algorithm + * @details + * The Chinese Remainder Theorem (CRT) is used to solve systems of + * simultaneous congruences. Given several pairwise coprime moduli + * and corresponding remainders, the algorithm finds the smallest + * positive solution. + */ +public final class ChineseRemainderTheorem { + private ChineseRemainderTheorem() { + } + + /** + * @brief Solves the Chinese Remainder Theorem problem. + * @param remainders The list of remainders. + * @param moduli The list of pairwise coprime moduli. + * @return The smallest positive solution that satisfies all the given congruences. + */ + public static int solveCRT(List remainders, List moduli) { + int product = 1; + int result = 0; + + // Calculate the product of all moduli + for (int mod : moduli) { + product *= mod; + } + + // Apply the formula for each congruence + for (int i = 0; i < moduli.size(); i++) { + int partialProduct = product / moduli.get(i); + int inverse = modInverse(partialProduct, moduli.get(i)); + result += remainders.get(i) * partialProduct * inverse; + } + + // The result should be modulo product to find the smallest positive solution + return result % product; + } + + /** + * @brief Computes the modular inverse of a number with respect to a modulus using + * the Extended Euclidean Algorithm. + * @param a The number for which to find the inverse. + * @param m The modulus. + * @return The modular inverse of a modulo m. + */ + private static int modInverse(int a, int m) { + int m0 = m, x0 = 0, x1 = 1; + + if (m == 1) return 0; + + while (a > 1) { + int q = a / m; + int t = m; + + // m is remainder now, process same as Euclid's algorithm + m = a % m; + a = t; + t = x0; + + x0 = x1 - q * x0; + x1 = t; + } + + // Make x1 positive + if (x1 < 0) { + x1 += m0; + } + + return x1; + } +} diff --git a/src/test/java/com/thealgorithms/maths/ChineseRemainderTheoremTest.java b/src/test/java/com/thealgorithms/maths/ChineseRemainderTheoremTest.java new file mode 100644 index 000000000000..a290a92cd453 --- /dev/null +++ b/src/test/java/com/thealgorithms/maths/ChineseRemainderTheoremTest.java @@ -0,0 +1,75 @@ +package com.thealgorithms.maths; + +import java.util.List; + +/** + * @brief Implementation of the Chinese Remainder Theorem (CRT) algorithm + * @details + * The Chinese Remainder Theorem (CRT) is used to solve systems of + * simultaneous congruences. Given several pairwise coprime moduli + * and corresponding remainders, the algorithm finds the smallest + * positive solution. + */ +public final class ChineseRemainderTheorem { + private ChineseRemainderTheorem() { + } + + /** + * @brief Solves the Chinese Remainder Theorem problem. + * @param remainders The list of remainders. + * @param moduli The list of pairwise coprime moduli. + * @return The smallest positive solution that satisfies all the given congruences. + */ + public static int solveCRT(List remainders, List moduli) { + int product = 1; + int result = 0; + + // Calculate the product of all moduli + for (int mod : moduli) { + product *= mod; + } + + // Apply the formula for each congruence + for (int i = 0; i < moduli.size(); i++) { + int partialProduct = product / moduli.get(i); + int inverse = modInverse(partialProduct, moduli.get(i)); + result += remainders.get(i) * partialProduct * inverse; + } + + // The result should be modulo product to find the smallest positive solution + return result % product; + } + + /** + * @brief Computes the modular inverse of a number with respect to a modulus using + * the Extended Euclidean Algorithm. + * @param a The number for which to find the inverse. + * @param m The modulus. + * @return The modular inverse of a modulo m. + */ + private static int modInverse(int a, int m) { + int m0 = m, x0 = 0, x1 = 1; + + if (m == 1) return 0; + + while (a > 1) { + int q = a / m; + int t = m; + + // m is remainder now, process same as Euclid's algorithm + m = a % m; + a = t; + t = x0; + + x0 = x1 - q * x0; + x1 = t; + } + + // Make x1 positive + if (x1 < 0) { + x1 += m0; + } + + return x1; + } +} From 2a2d96525090a4cf6c49c6afd210b61914d27261 Mon Sep 17 00:00:00 2001 From: suprhulk Date: Wed, 16 Oct 2024 17:30:49 +0530 Subject: [PATCH 02/10] Fix errors and update code as per review comments --- .../com/thealgorithms/maths/ChineseRemainderTheoremTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/java/com/thealgorithms/maths/ChineseRemainderTheoremTest.java b/src/test/java/com/thealgorithms/maths/ChineseRemainderTheoremTest.java index a290a92cd453..b14ea05747a4 100644 --- a/src/test/java/com/thealgorithms/maths/ChineseRemainderTheoremTest.java +++ b/src/test/java/com/thealgorithms/maths/ChineseRemainderTheoremTest.java @@ -10,8 +10,8 @@ * and corresponding remainders, the algorithm finds the smallest * positive solution. */ -public final class ChineseRemainderTheorem { - private ChineseRemainderTheorem() { +public final class ChineseRemainderTheoremTest { + private ChineseRemainderTheoremTest() { } /** From 7cdee730b9f57e65f8e138db6afb4aacdd6700ad Mon Sep 17 00:00:00 2001 From: suprhulk Date: Wed, 16 Oct 2024 17:38:02 +0530 Subject: [PATCH 03/10] chore: Refactor Chinese Remainder Theorem test code --- .../maths/ChineseRemainderTheoremTest.java | 108 +++++++----------- 1 file changed, 44 insertions(+), 64 deletions(-) diff --git a/src/test/java/com/thealgorithms/maths/ChineseRemainderTheoremTest.java b/src/test/java/com/thealgorithms/maths/ChineseRemainderTheoremTest.java index b14ea05747a4..e63795ca3992 100644 --- a/src/test/java/com/thealgorithms/maths/ChineseRemainderTheoremTest.java +++ b/src/test/java/com/thealgorithms/maths/ChineseRemainderTheoremTest.java @@ -1,75 +1,55 @@ package com.thealgorithms.maths; -import java.util.List; +import static org.junit.jupiter.api.Assertions.assertEquals; -/** - * @brief Implementation of the Chinese Remainder Theorem (CRT) algorithm - * @details - * The Chinese Remainder Theorem (CRT) is used to solve systems of - * simultaneous congruences. Given several pairwise coprime moduli - * and corresponding remainders, the algorithm finds the smallest - * positive solution. - */ -public final class ChineseRemainderTheoremTest { - private ChineseRemainderTheoremTest() { +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import org.junit.jupiter.api.Test; + +public class ChineseRemainderTheoremTest { + @Test + public void testCRTSimpleCase() { + List remainders = Arrays.asList(2, 3, 2); + List moduli = Arrays.asList(3, 5, 7); + int expected = 23; + int result = ChineseRemainderTheorem.solveCRT(remainders, moduli); + assertEquals(expected, result); } - /** - * @brief Solves the Chinese Remainder Theorem problem. - * @param remainders The list of remainders. - * @param moduli The list of pairwise coprime moduli. - * @return The smallest positive solution that satisfies all the given congruences. - */ - public static int solveCRT(List remainders, List moduli) { - int product = 1; - int result = 0; - - // Calculate the product of all moduli - for (int mod : moduli) { - product *= mod; - } - - // Apply the formula for each congruence - for (int i = 0; i < moduli.size(); i++) { - int partialProduct = product / moduli.get(i); - int inverse = modInverse(partialProduct, moduli.get(i)); - result += remainders.get(i) * partialProduct * inverse; - } - - // The result should be modulo product to find the smallest positive solution - return result % product; + @Test + public void testCRTLargeModuli() { + List remainders = Arrays.asList(1, 2, 3); + List moduli = Arrays.asList(5, 7, 9); + int expected = 131; + int result = ChineseRemainderTheorem.solveCRT(remainders, moduli); + assertEquals(expected, result); } - /** - * @brief Computes the modular inverse of a number with respect to a modulus using - * the Extended Euclidean Algorithm. - * @param a The number for which to find the inverse. - * @param m The modulus. - * @return The modular inverse of a modulo m. - */ - private static int modInverse(int a, int m) { - int m0 = m, x0 = 0, x1 = 1; - - if (m == 1) return 0; - - while (a > 1) { - int q = a / m; - int t = m; - - // m is remainder now, process same as Euclid's algorithm - m = a % m; - a = t; - t = x0; - - x0 = x1 - q * x0; - x1 = t; - } + @Test + public void testCRTWithSingleCongruence() { + List remainders = Arrays.asList(4); + List moduli = Arrays.asList(7); + int expected = 4; + int result = ChineseRemainderTheorem.solveCRT(remainders, moduli); + assertEquals(expected, result); + } - // Make x1 positive - if (x1 < 0) { - x1 += m0; - } + @Test + public void testCRTWithMultipleSolutions() { + List remainders = Arrays.asList(0, 3); + List moduli = Arrays.asList(4, 5); + int expected = 15; + int result = ChineseRemainderTheorem.solveCRT(remainders, moduli); + assertEquals(expected, result); + } - return x1; + @Test + public void testCRTLargeNumbers() { + List remainders = Arrays.asList(0, 4, 6); + List moduli = Arrays.asList(11, 13, 17); + int expected = 782; + int result = ChineseRemainderTheorem.solveCRT(remainders, moduli); + assertEquals(expected, result); } } From 0a6e33e11d2887f1f59091fe7dfa8164f689b4cb Mon Sep 17 00:00:00 2001 From: suprhulk Date: Wed, 16 Oct 2024 17:38:23 +0530 Subject: [PATCH 04/10] Removed trailing spaces and added braces --- .../maths/ChineseRemainderTheorem.java | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/thealgorithms/maths/ChineseRemainderTheorem.java b/src/main/java/com/thealgorithms/maths/ChineseRemainderTheorem.java index a290a92cd453..acc4ab925984 100644 --- a/src/main/java/com/thealgorithms/maths/ChineseRemainderTheorem.java +++ b/src/main/java/com/thealgorithms/maths/ChineseRemainderTheorem.java @@ -5,9 +5,9 @@ /** * @brief Implementation of the Chinese Remainder Theorem (CRT) algorithm * @details - * The Chinese Remainder Theorem (CRT) is used to solve systems of - * simultaneous congruences. Given several pairwise coprime moduli - * and corresponding remainders, the algorithm finds the smallest + * The Chinese Remainder Theorem (CRT) is used to solve systems of + * simultaneous congruences. Given several pairwise coprime moduli + * and corresponding remainders, the algorithm finds the smallest * positive solution. */ public final class ChineseRemainderTheorem { @@ -48,9 +48,13 @@ public static int solveCRT(List remainders, List moduli) { * @return The modular inverse of a modulo m. */ private static int modInverse(int a, int m) { - int m0 = m, x0 = 0, x1 = 1; + int m0 = m; + int x0 = 0; + int x1 = 1; - if (m == 1) return 0; + if (m == 1) { + return 0 + }; while (a > 1) { int q = a / m; From fcac2b163bbc802a45549d39ad9546cd447c89f1 Mon Sep 17 00:00:00 2001 From: suprhulk Date: Wed, 16 Oct 2024 17:39:44 +0530 Subject: [PATCH 05/10] Fix missing semicolon in ChineseRemainderTheorem class --- .../java/com/thealgorithms/maths/ChineseRemainderTheorem.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/thealgorithms/maths/ChineseRemainderTheorem.java b/src/main/java/com/thealgorithms/maths/ChineseRemainderTheorem.java index acc4ab925984..86b5f29bfc56 100644 --- a/src/main/java/com/thealgorithms/maths/ChineseRemainderTheorem.java +++ b/src/main/java/com/thealgorithms/maths/ChineseRemainderTheorem.java @@ -53,7 +53,7 @@ private static int modInverse(int a, int m) { int x1 = 1; if (m == 1) { - return 0 + return 0; }; while (a > 1) { From da99a7385ef23fb77961eaef90ba937ac6702a3f Mon Sep 17 00:00:00 2001 From: suprhulk Date: Wed, 16 Oct 2024 18:02:33 +0530 Subject: [PATCH 06/10] chore: Adjust result to be the smallest positive solution in ChineseRemainderTheorem --- .../com/thealgorithms/maths/ChineseRemainderTheorem.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/thealgorithms/maths/ChineseRemainderTheorem.java b/src/main/java/com/thealgorithms/maths/ChineseRemainderTheorem.java index 86b5f29bfc56..185e1772de16 100644 --- a/src/main/java/com/thealgorithms/maths/ChineseRemainderTheorem.java +++ b/src/main/java/com/thealgorithms/maths/ChineseRemainderTheorem.java @@ -36,8 +36,13 @@ public static int solveCRT(List remainders, List moduli) { result += remainders.get(i) * partialProduct * inverse; } - // The result should be modulo product to find the smallest positive solution - return result % product; + // Adjust result to be the smallest positive solution + result = result % product; + if (result < 0) { + result += product; + } + + return result; } /** From 460d992922194361a22867f91954d2f1b6db500a Mon Sep 17 00:00:00 2001 From: suprhulk Date: Wed, 16 Oct 2024 18:13:41 +0530 Subject: [PATCH 07/10] chore: Adjust result to be the smallest positive solution in ChineseRemainderTheorem --- .../thealgorithms/maths/ChineseRemainderTheoremTest.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/test/java/com/thealgorithms/maths/ChineseRemainderTheoremTest.java b/src/test/java/com/thealgorithms/maths/ChineseRemainderTheoremTest.java index e63795ca3992..b09ece2c5e01 100644 --- a/src/test/java/com/thealgorithms/maths/ChineseRemainderTheoremTest.java +++ b/src/test/java/com/thealgorithms/maths/ChineseRemainderTheoremTest.java @@ -21,7 +21,7 @@ public void testCRTSimpleCase() { public void testCRTLargeModuli() { List remainders = Arrays.asList(1, 2, 3); List moduli = Arrays.asList(5, 7, 9); - int expected = 131; + int expected = 156; int result = ChineseRemainderTheorem.solveCRT(remainders, moduli); assertEquals(expected, result); } @@ -39,7 +39,7 @@ public void testCRTWithSingleCongruence() { public void testCRTWithMultipleSolutions() { List remainders = Arrays.asList(0, 3); List moduli = Arrays.asList(4, 5); - int expected = 15; + int expected = 8; int result = ChineseRemainderTheorem.solveCRT(remainders, moduli); assertEquals(expected, result); } @@ -48,7 +48,7 @@ public void testCRTWithMultipleSolutions() { public void testCRTLargeNumbers() { List remainders = Arrays.asList(0, 4, 6); List moduli = Arrays.asList(11, 13, 17); - int expected = 782; + int expected = 550; int result = ChineseRemainderTheorem.solveCRT(remainders, moduli); assertEquals(expected, result); } From 0d6136344e50ddd10289bc6003fa76d03fff363d Mon Sep 17 00:00:00 2001 From: suprhulk Date: Wed, 16 Oct 2024 18:18:20 +0530 Subject: [PATCH 08/10] "Fix checkstyle violations" --- .../java/com/thealgorithms/maths/ChineseRemainderTheorem.java | 2 +- .../com/thealgorithms/maths/ChineseRemainderTheoremTest.java | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/java/com/thealgorithms/maths/ChineseRemainderTheorem.java b/src/main/java/com/thealgorithms/maths/ChineseRemainderTheorem.java index 185e1772de16..c26e67cffb59 100644 --- a/src/main/java/com/thealgorithms/maths/ChineseRemainderTheorem.java +++ b/src/main/java/com/thealgorithms/maths/ChineseRemainderTheorem.java @@ -59,7 +59,7 @@ private static int modInverse(int a, int m) { if (m == 1) { return 0; - }; + } while (a > 1) { int q = a / m; diff --git a/src/test/java/com/thealgorithms/maths/ChineseRemainderTheoremTest.java b/src/test/java/com/thealgorithms/maths/ChineseRemainderTheoremTest.java index b09ece2c5e01..eba1562f27cc 100644 --- a/src/test/java/com/thealgorithms/maths/ChineseRemainderTheoremTest.java +++ b/src/test/java/com/thealgorithms/maths/ChineseRemainderTheoremTest.java @@ -4,7 +4,6 @@ import java.util.ArrayList; import java.util.Arrays; -import java.util.List; import org.junit.jupiter.api.Test; public class ChineseRemainderTheoremTest { From 92c6211d9fe47c4d2a2e5ffb4d9e0e81bbd4f743 Mon Sep 17 00:00:00 2001 From: suprhulk Date: Wed, 16 Oct 2024 18:20:20 +0530 Subject: [PATCH 09/10] chore: Adjust result to be the smallest positive solution in ChineseRemainderTheorem --- .../thealgorithms/maths/ChineseRemainderTheoremTest.java | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/test/java/com/thealgorithms/maths/ChineseRemainderTheoremTest.java b/src/test/java/com/thealgorithms/maths/ChineseRemainderTheoremTest.java index eba1562f27cc..1ccf0875200e 100644 --- a/src/test/java/com/thealgorithms/maths/ChineseRemainderTheoremTest.java +++ b/src/test/java/com/thealgorithms/maths/ChineseRemainderTheoremTest.java @@ -1,8 +1,7 @@ package com.thealgorithms.maths; import static org.junit.jupiter.api.Assertions.assertEquals; - -import java.util.ArrayList; +import java.util.List; import java.util.Arrays; import org.junit.jupiter.api.Test; @@ -20,7 +19,7 @@ public void testCRTSimpleCase() { public void testCRTLargeModuli() { List remainders = Arrays.asList(1, 2, 3); List moduli = Arrays.asList(5, 7, 9); - int expected = 156; + int expected = 131; int result = ChineseRemainderTheorem.solveCRT(remainders, moduli); assertEquals(expected, result); } @@ -38,7 +37,7 @@ public void testCRTWithSingleCongruence() { public void testCRTWithMultipleSolutions() { List remainders = Arrays.asList(0, 3); List moduli = Arrays.asList(4, 5); - int expected = 8; + int expected = 15; int result = ChineseRemainderTheorem.solveCRT(remainders, moduli); assertEquals(expected, result); } @@ -47,7 +46,7 @@ public void testCRTWithMultipleSolutions() { public void testCRTLargeNumbers() { List remainders = Arrays.asList(0, 4, 6); List moduli = Arrays.asList(11, 13, 17); - int expected = 550; + int expected = 782; int result = ChineseRemainderTheorem.solveCRT(remainders, moduli); assertEquals(expected, result); } From 62fcbb8a9388a82f30a75836ae027b32ead93e96 Mon Sep 17 00:00:00 2001 From: suprhulk Date: Wed, 16 Oct 2024 18:23:15 +0530 Subject: [PATCH 10/10] chore: Adjust result to be the smallest positive solution in ChineseRemainderTheorem --- .../thealgorithms/maths/ChineseRemainderTheoremTest.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/test/java/com/thealgorithms/maths/ChineseRemainderTheoremTest.java b/src/test/java/com/thealgorithms/maths/ChineseRemainderTheoremTest.java index 1ccf0875200e..31c676d6e7b4 100644 --- a/src/test/java/com/thealgorithms/maths/ChineseRemainderTheoremTest.java +++ b/src/test/java/com/thealgorithms/maths/ChineseRemainderTheoremTest.java @@ -1,8 +1,9 @@ package com.thealgorithms.maths; import static org.junit.jupiter.api.Assertions.assertEquals; -import java.util.List; + import java.util.Arrays; +import java.util.List; import org.junit.jupiter.api.Test; public class ChineseRemainderTheoremTest { @@ -19,7 +20,7 @@ public void testCRTSimpleCase() { public void testCRTLargeModuli() { List remainders = Arrays.asList(1, 2, 3); List moduli = Arrays.asList(5, 7, 9); - int expected = 131; + int expected = 156; int result = ChineseRemainderTheorem.solveCRT(remainders, moduli); assertEquals(expected, result); } @@ -37,7 +38,7 @@ public void testCRTWithSingleCongruence() { public void testCRTWithMultipleSolutions() { List remainders = Arrays.asList(0, 3); List moduli = Arrays.asList(4, 5); - int expected = 15; + int expected = 8; int result = ChineseRemainderTheorem.solveCRT(remainders, moduli); assertEquals(expected, result); } @@ -46,7 +47,7 @@ public void testCRTWithMultipleSolutions() { public void testCRTLargeNumbers() { List remainders = Arrays.asList(0, 4, 6); List moduli = Arrays.asList(11, 13, 17); - int expected = 782; + int expected = 550; int result = ChineseRemainderTheorem.solveCRT(remainders, moduli); assertEquals(expected, result); }