Skip to content

Commit 5493aa5

Browse files
committed
Add Sum of Squares algorithm implementation
1 parent f8f315e commit 5493aa5

File tree

2 files changed

+106
-0
lines changed

2 files changed

+106
-0
lines changed
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
package com.thealgorithms.maths;
2+
3+
/**
4+
* Implementation of Lagrange's Four Square Theorem
5+
* Find minimum number of perfect squares that sum to given number
6+
* @author BEASTSHRIRAM
7+
*/
8+
public final class SumOfSquares {
9+
10+
private SumOfSquares() {
11+
// Utility class
12+
}
13+
14+
/**
15+
* Find minimum number of perfect squares that sum to n
16+
* @param n the target number
17+
* @return minimum number of squares needed
18+
*/
19+
public static int minSquares(int n) {
20+
if (isPerfectSquare(n)) return 1;
21+
22+
for (int i = 1; i * i <= n; i++) {
23+
int remaining = n - i * i;
24+
if (isPerfectSquare(remaining)) return 2;
25+
}
26+
27+
// Legendre's three-square theorem
28+
int temp = n;
29+
while (temp % 4 == 0) temp /= 4;
30+
if (temp % 8 == 7) return 4;
31+
32+
return 3;
33+
}
34+
35+
private static boolean isPerfectSquare(int n) {
36+
if (n < 0) return false;
37+
int root = (int) Math.sqrt(n);
38+
return root * root == n;
39+
}
40+
}
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
package com.thealgorithms.maths;
2+
3+
import static org.junit.jupiter.api.Assertions.assertEquals;
4+
import org.junit.jupiter.api.Test;
5+
6+
/**
7+
* Test class for SumOfSquares
8+
* @author BEASTSHRIRAM
9+
*/
10+
class SumOfSquaresTest {
11+
12+
@Test
13+
void testPerfectSquares() {
14+
// Perfect squares should return 1
15+
assertEquals(1, SumOfSquares.minSquares(1)); // 1^2
16+
assertEquals(1, SumOfSquares.minSquares(4)); // 2^2
17+
assertEquals(1, SumOfSquares.minSquares(9)); // 3^2
18+
assertEquals(1, SumOfSquares.minSquares(16)); // 4^2
19+
assertEquals(1, SumOfSquares.minSquares(25)); // 5^2
20+
}
21+
22+
@Test
23+
void testTwoSquares() {
24+
// Numbers that can be expressed as sum of two squares
25+
assertEquals(2, SumOfSquares.minSquares(2)); // 1^2 + 1^2
26+
assertEquals(2, SumOfSquares.minSquares(5)); // 1^2 + 2^2
27+
assertEquals(2, SumOfSquares.minSquares(8)); // 2^2 + 2^2
28+
assertEquals(2, SumOfSquares.minSquares(10)); // 1^2 + 3^2
29+
assertEquals(2, SumOfSquares.minSquares(13)); // 2^2 + 3^2
30+
}
31+
32+
@Test
33+
void testThreeSquares() {
34+
// Numbers that require exactly three squares
35+
assertEquals(3, SumOfSquares.minSquares(3)); // 1^2 + 1^2 + 1^2
36+
assertEquals(3, SumOfSquares.minSquares(6)); // 1^2 + 1^2 + 2^2
37+
assertEquals(3, SumOfSquares.minSquares(11)); // 1^2 + 1^2 + 3^2
38+
assertEquals(3, SumOfSquares.minSquares(12)); // 2^2 + 2^2 + 2^2
39+
assertEquals(3, SumOfSquares.minSquares(14)); // 1^2 + 2^2 + 3^2
40+
}
41+
42+
@Test
43+
void testFourSquares() {
44+
// Numbers that require exactly four squares (form 4^a * (8b + 7))
45+
assertEquals(4, SumOfSquares.minSquares(7)); // 1^2 + 1^2 + 1^2 + 2^2
46+
assertEquals(4, SumOfSquares.minSquares(15)); // 1^2 + 1^2 + 2^2 + 3^2
47+
assertEquals(4, SumOfSquares.minSquares(23)); // 1^2 + 1^2 + 3^2 + 3^2
48+
assertEquals(4, SumOfSquares.minSquares(28)); // 4 * 7, so needs 4 squares
49+
assertEquals(4, SumOfSquares.minSquares(31)); // 1^2 + 2^2 + 3^2 + 3^2
50+
}
51+
52+
@Test
53+
void testLargerNumbers() {
54+
// Test some larger numbers
55+
assertEquals(1, SumOfSquares.minSquares(100)); // 10^2
56+
assertEquals(2, SumOfSquares.minSquares(65)); // 1^2 + 8^2
57+
assertEquals(3, SumOfSquares.minSquares(19)); // 1^2 + 3^2 + 3^2
58+
assertEquals(4, SumOfSquares.minSquares(60)); // 4 * 15, and 15 = 8*1 + 7
59+
}
60+
61+
@Test
62+
void testEdgeCases() {
63+
// Test edge case
64+
assertEquals(1, SumOfSquares.minSquares(0)); // 0^2
65+
}
66+
}

0 commit comments

Comments
 (0)