Added Sum of Squares Lagrange's Four Square algorithm implementation (#6583)

* Add Sum of Squares algorithm implementation

* Format code and add Wikipedia URL for Lagrange's theorem

* Fixed clang-format issues

---------

Co-authored-by: Oleksandr Klymenko <alexanderklmn@gmail.com>
This commit is contained in:
Sriram kulkarni
2025-10-02 13:14:36 +05:30
committed by GitHub
parent 15695c6e54
commit d8ddb07b7e
2 changed files with 121 additions and 0 deletions

View File

@@ -0,0 +1,53 @@
package com.thealgorithms.maths;
/**
* Implementation of Lagrange's Four Square Theorem
* Find minimum number of perfect squares that sum to given number
*
* @see <a href="https://en.wikipedia.org/wiki/Lagrange%27s_four-square_theorem">Lagrange's Four Square Theorem</a>
* @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;
}
}

View File

@@ -0,0 +1,68 @@
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
}
}