From 5493aa534b87b97d46b87470207ebfd1e1f24313 Mon Sep 17 00:00:00 2001 From: shriramthebeast Date: Thu, 2 Oct 2025 11:24:53 +0530 Subject: [PATCH 1/3] Add Sum of Squares algorithm implementation --- .../com/thealgorithms/maths/SumOfSquares.java | 40 +++++++++++ .../thealgorithms/maths/SumOfSquaresTest.java | 66 +++++++++++++++++++ 2 files changed, 106 insertions(+) create mode 100644 src/main/java/com/thealgorithms/maths/SumOfSquares.java create mode 100644 src/test/java/com/thealgorithms/maths/SumOfSquaresTest.java diff --git a/src/main/java/com/thealgorithms/maths/SumOfSquares.java b/src/main/java/com/thealgorithms/maths/SumOfSquares.java new file mode 100644 index 000000000000..66aabb315ef2 --- /dev/null +++ b/src/main/java/com/thealgorithms/maths/SumOfSquares.java @@ -0,0 +1,40 @@ +package com.thealgorithms.maths; + +/** + * Implementation of Lagrange's Four Square Theorem + * Find minimum number of perfect squares that sum to given number + * @author BEASTSHRIRAM + */ +public final class SumOfSquares { + + private SumOfSquares() { + // Utility class + } + + /** + * Find minimum number of perfect squares that sum to n + * @param n the target number + * @return minimum number of squares needed + */ + public static int minSquares(int n) { + if (isPerfectSquare(n)) return 1; + + for (int i = 1; i * i <= n; i++) { + int remaining = n - i * i; + if (isPerfectSquare(remaining)) return 2; + } + + // Legendre's three-square theorem + int temp = n; + while (temp % 4 == 0) temp /= 4; + if (temp % 8 == 7) return 4; + + return 3; + } + + private static boolean isPerfectSquare(int n) { + if (n < 0) return false; + int root = (int) Math.sqrt(n); + return root * root == n; + } +} \ No newline at end of file diff --git a/src/test/java/com/thealgorithms/maths/SumOfSquaresTest.java b/src/test/java/com/thealgorithms/maths/SumOfSquaresTest.java new file mode 100644 index 000000000000..50ab43a8ff39 --- /dev/null +++ b/src/test/java/com/thealgorithms/maths/SumOfSquaresTest.java @@ -0,0 +1,66 @@ +package com.thealgorithms.maths; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import org.junit.jupiter.api.Test; + +/** + * Test class for SumOfSquares + * @author BEASTSHRIRAM + */ +class SumOfSquaresTest { + + @Test + void testPerfectSquares() { + // Perfect squares should return 1 + assertEquals(1, SumOfSquares.minSquares(1)); // 1^2 + assertEquals(1, SumOfSquares.minSquares(4)); // 2^2 + assertEquals(1, SumOfSquares.minSquares(9)); // 3^2 + assertEquals(1, SumOfSquares.minSquares(16)); // 4^2 + assertEquals(1, SumOfSquares.minSquares(25)); // 5^2 + } + + @Test + void testTwoSquares() { + // Numbers that can be expressed as sum of two squares + assertEquals(2, SumOfSquares.minSquares(2)); // 1^2 + 1^2 + assertEquals(2, SumOfSquares.minSquares(5)); // 1^2 + 2^2 + assertEquals(2, SumOfSquares.minSquares(8)); // 2^2 + 2^2 + assertEquals(2, SumOfSquares.minSquares(10)); // 1^2 + 3^2 + assertEquals(2, SumOfSquares.minSquares(13)); // 2^2 + 3^2 + } + + @Test + void testThreeSquares() { + // Numbers that require exactly three squares + assertEquals(3, SumOfSquares.minSquares(3)); // 1^2 + 1^2 + 1^2 + assertEquals(3, SumOfSquares.minSquares(6)); // 1^2 + 1^2 + 2^2 + assertEquals(3, SumOfSquares.minSquares(11)); // 1^2 + 1^2 + 3^2 + assertEquals(3, SumOfSquares.minSquares(12)); // 2^2 + 2^2 + 2^2 + assertEquals(3, SumOfSquares.minSquares(14)); // 1^2 + 2^2 + 3^2 + } + + @Test + void testFourSquares() { + // Numbers that require exactly four squares (form 4^a * (8b + 7)) + assertEquals(4, SumOfSquares.minSquares(7)); // 1^2 + 1^2 + 1^2 + 2^2 + assertEquals(4, SumOfSquares.minSquares(15)); // 1^2 + 1^2 + 2^2 + 3^2 + assertEquals(4, SumOfSquares.minSquares(23)); // 1^2 + 1^2 + 3^2 + 3^2 + assertEquals(4, SumOfSquares.minSquares(28)); // 4 * 7, so needs 4 squares + assertEquals(4, SumOfSquares.minSquares(31)); // 1^2 + 2^2 + 3^2 + 3^2 + } + + @Test + void testLargerNumbers() { + // Test some larger numbers + assertEquals(1, SumOfSquares.minSquares(100)); // 10^2 + assertEquals(2, SumOfSquares.minSquares(65)); // 1^2 + 8^2 + assertEquals(3, SumOfSquares.minSquares(19)); // 1^2 + 3^2 + 3^2 + assertEquals(4, SumOfSquares.minSquares(60)); // 4 * 15, and 15 = 8*1 + 7 + } + + @Test + void testEdgeCases() { + // Test edge case + assertEquals(1, SumOfSquares.minSquares(0)); // 0^2 + } +} \ No newline at end of file From 3e9f0399de5b1c29410a0f69978ac6cdbeccc59e Mon Sep 17 00:00:00 2001 From: shriramthebeast Date: Thu, 2 Oct 2025 11:29:36 +0530 Subject: [PATCH 2/3] Format code and add Wikipedia URL for Lagrange's theorem --- .../com/thealgorithms/maths/SumOfSquares.java | 35 +++++++++---- .../thealgorithms/maths/SumOfSquaresTest.java | 50 ++++++++++--------- 2 files changed, 50 insertions(+), 35 deletions(-) diff --git a/src/main/java/com/thealgorithms/maths/SumOfSquares.java b/src/main/java/com/thealgorithms/maths/SumOfSquares.java index 66aabb315ef2..bdae6665edc3 100644 --- a/src/main/java/com/thealgorithms/maths/SumOfSquares.java +++ b/src/main/java/com/thealgorithms/maths/SumOfSquares.java @@ -3,37 +3,50 @@ /** * Implementation of Lagrange's Four Square Theorem * Find minimum number of perfect squares that sum to given number + * + * @see Lagrange's Four Square Theorem * @author BEASTSHRIRAM */ public final class SumOfSquares { - + private SumOfSquares() { // Utility class } - + /** * Find minimum number of perfect squares that sum to n + * * @param n the target number * @return minimum number of squares needed */ public static int minSquares(int n) { - if (isPerfectSquare(n)) return 1; - + if (isPerfectSquare(n)) { + return 1; + } + for (int i = 1; i * i <= n; i++) { int remaining = n - i * i; - if (isPerfectSquare(remaining)) return 2; + if (isPerfectSquare(remaining)) { + return 2; + } } - + // Legendre's three-square theorem int temp = n; - while (temp % 4 == 0) temp /= 4; - if (temp % 8 == 7) return 4; - + while (temp % 4 == 0) { + temp /= 4; + } + if (temp % 8 == 7) { + return 4; + } + return 3; } - + private static boolean isPerfectSquare(int n) { - if (n < 0) return false; + if (n < 0) { + return false; + } int root = (int) Math.sqrt(n); return root * root == n; } diff --git a/src/test/java/com/thealgorithms/maths/SumOfSquaresTest.java b/src/test/java/com/thealgorithms/maths/SumOfSquaresTest.java index 50ab43a8ff39..a87b0f6ad145 100644 --- a/src/test/java/com/thealgorithms/maths/SumOfSquaresTest.java +++ b/src/test/java/com/thealgorithms/maths/SumOfSquaresTest.java @@ -1,10 +1,12 @@ package com.thealgorithms.maths; import static org.junit.jupiter.api.Assertions.assertEquals; + import org.junit.jupiter.api.Test; /** * Test class for SumOfSquares + * * @author BEASTSHRIRAM */ class SumOfSquaresTest { @@ -12,55 +14,55 @@ class SumOfSquaresTest { @Test void testPerfectSquares() { // Perfect squares should return 1 - assertEquals(1, SumOfSquares.minSquares(1)); // 1^2 - assertEquals(1, SumOfSquares.minSquares(4)); // 2^2 - assertEquals(1, SumOfSquares.minSquares(9)); // 3^2 - assertEquals(1, SumOfSquares.minSquares(16)); // 4^2 - assertEquals(1, SumOfSquares.minSquares(25)); // 5^2 + assertEquals(1, SumOfSquares.minSquares(1)); // 1^2 + assertEquals(1, SumOfSquares.minSquares(4)); // 2^2 + assertEquals(1, SumOfSquares.minSquares(9)); // 3^2 + assertEquals(1, SumOfSquares.minSquares(16)); // 4^2 + assertEquals(1, SumOfSquares.minSquares(25)); // 5^2 } @Test void testTwoSquares() { // Numbers that can be expressed as sum of two squares - assertEquals(2, SumOfSquares.minSquares(2)); // 1^2 + 1^2 - assertEquals(2, SumOfSquares.minSquares(5)); // 1^2 + 2^2 - assertEquals(2, SumOfSquares.minSquares(8)); // 2^2 + 2^2 - assertEquals(2, SumOfSquares.minSquares(10)); // 1^2 + 3^2 - assertEquals(2, SumOfSquares.minSquares(13)); // 2^2 + 3^2 + assertEquals(2, SumOfSquares.minSquares(2)); // 1^2 + 1^2 + assertEquals(2, SumOfSquares.minSquares(5)); // 1^2 + 2^2 + assertEquals(2, SumOfSquares.minSquares(8)); // 2^2 + 2^2 + assertEquals(2, SumOfSquares.minSquares(10)); // 1^2 + 3^2 + assertEquals(2, SumOfSquares.minSquares(13)); // 2^2 + 3^2 } @Test void testThreeSquares() { // Numbers that require exactly three squares - assertEquals(3, SumOfSquares.minSquares(3)); // 1^2 + 1^2 + 1^2 - assertEquals(3, SumOfSquares.minSquares(6)); // 1^2 + 1^2 + 2^2 - assertEquals(3, SumOfSquares.minSquares(11)); // 1^2 + 1^2 + 3^2 - assertEquals(3, SumOfSquares.minSquares(12)); // 2^2 + 2^2 + 2^2 - assertEquals(3, SumOfSquares.minSquares(14)); // 1^2 + 2^2 + 3^2 + assertEquals(3, SumOfSquares.minSquares(3)); // 1^2 + 1^2 + 1^2 + assertEquals(3, SumOfSquares.minSquares(6)); // 1^2 + 1^2 + 2^2 + assertEquals(3, SumOfSquares.minSquares(11)); // 1^2 + 1^2 + 3^2 + assertEquals(3, SumOfSquares.minSquares(12)); // 2^2 + 2^2 + 2^2 + assertEquals(3, SumOfSquares.minSquares(14)); // 1^2 + 2^2 + 3^2 } @Test void testFourSquares() { // Numbers that require exactly four squares (form 4^a * (8b + 7)) - assertEquals(4, SumOfSquares.minSquares(7)); // 1^2 + 1^2 + 1^2 + 2^2 - assertEquals(4, SumOfSquares.minSquares(15)); // 1^2 + 1^2 + 2^2 + 3^2 - assertEquals(4, SumOfSquares.minSquares(23)); // 1^2 + 1^2 + 3^2 + 3^2 - assertEquals(4, SumOfSquares.minSquares(28)); // 4 * 7, so needs 4 squares - assertEquals(4, SumOfSquares.minSquares(31)); // 1^2 + 2^2 + 3^2 + 3^2 + assertEquals(4, SumOfSquares.minSquares(7)); // 1^2 + 1^2 + 1^2 + 2^2 + assertEquals(4, SumOfSquares.minSquares(15)); // 1^2 + 1^2 + 2^2 + 3^2 + assertEquals(4, SumOfSquares.minSquares(23)); // 1^2 + 1^2 + 3^2 + 3^2 + assertEquals(4, SumOfSquares.minSquares(28)); // 4 * 7, so needs 4 squares + assertEquals(4, SumOfSquares.minSquares(31)); // 1^2 + 2^2 + 3^2 + 3^2 } @Test void testLargerNumbers() { // Test some larger numbers assertEquals(1, SumOfSquares.minSquares(100)); // 10^2 - assertEquals(2, SumOfSquares.minSquares(65)); // 1^2 + 8^2 - assertEquals(3, SumOfSquares.minSquares(19)); // 1^2 + 3^2 + 3^2 - assertEquals(4, SumOfSquares.minSquares(60)); // 4 * 15, and 15 = 8*1 + 7 + assertEquals(2, SumOfSquares.minSquares(65)); // 1^2 + 8^2 + assertEquals(3, SumOfSquares.minSquares(19)); // 1^2 + 3^2 + 3^2 + assertEquals(4, SumOfSquares.minSquares(60)); // 4 * 15, and 15 = 8*1 + 7 } @Test void testEdgeCases() { // Test edge case - assertEquals(1, SumOfSquares.minSquares(0)); // 0^2 + assertEquals(1, SumOfSquares.minSquares(0)); // 0^2 } } \ No newline at end of file From e71008fa3f8d1d94e6b3b7653b1d4590f3260701 Mon Sep 17 00:00:00 2001 From: shriramthebeast Date: Thu, 2 Oct 2025 11:42:30 +0530 Subject: [PATCH 3/3] Fixed clang-format issues --- src/main/java/com/thealgorithms/maths/SumOfSquares.java | 2 +- src/test/java/com/thealgorithms/maths/SumOfSquaresTest.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/thealgorithms/maths/SumOfSquares.java b/src/main/java/com/thealgorithms/maths/SumOfSquares.java index bdae6665edc3..c050d5a75f7b 100644 --- a/src/main/java/com/thealgorithms/maths/SumOfSquares.java +++ b/src/main/java/com/thealgorithms/maths/SumOfSquares.java @@ -50,4 +50,4 @@ private static boolean isPerfectSquare(int n) { int root = (int) Math.sqrt(n); return root * root == n; } -} \ No newline at end of file +} diff --git a/src/test/java/com/thealgorithms/maths/SumOfSquaresTest.java b/src/test/java/com/thealgorithms/maths/SumOfSquaresTest.java index a87b0f6ad145..834fe61a049e 100644 --- a/src/test/java/com/thealgorithms/maths/SumOfSquaresTest.java +++ b/src/test/java/com/thealgorithms/maths/SumOfSquaresTest.java @@ -65,4 +65,4 @@ void testEdgeCases() { // Test edge case assertEquals(1, SumOfSquares.minSquares(0)); // 0^2 } -} \ No newline at end of file +}