Skip to content

Commit 63af279

Browse files
committed
feat: add SociableNumber implementation
1 parent 6fbbc94 commit 63af279

2 files changed

Lines changed: 100 additions & 0 deletions

File tree

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+
/**
4+
* Sociable numbers are natural numbers that form a cyclic sequence where the
5+
* sum of proper divisors of each number equals the next number in the sequence,
6+
* with the sequence eventually returning to the starting number.
7+
* Amicable numbers are a special case of sociable numbers with a cycle length of 2.
8+
* Example: (12496, 14288, 15472, 14536, 14264) is a sociable cycle of length 5.
9+
*
10+
* @see <a href="https://en.wikipedia.org/wiki/Sociable_number">
11+
* Wikipedia: Sociable Number</a>
12+
*
13+
* @see AmicableNumber
14+
*/
15+
public final class SociableNumber {
16+
17+
private SociableNumber() {
18+
// Utility class
19+
}
20+
21+
/**
22+
* Calculates the sum of proper divisors of a number
23+
* (all divisors excluding the number itself).
24+
*
25+
* @param number the number to calculate proper divisors sum for
26+
* @return sum of proper divisors, or 0 if number is less than or equal to 0
27+
*/
28+
static int sumOfProperDivisors(final int number) {
29+
if (number <= 0) {
30+
return 0;
31+
}
32+
int sum = 0;
33+
for (int i = 1; i < number; i++) {
34+
if (number % i == 0) {
35+
sum += i;
36+
}
37+
}
38+
return sum;
39+
}
40+
41+
/**
42+
* Checks whether a number is part of a sociable cycle of a given length.
43+
* Starting from the given number, it follows the chain of proper divisor
44+
* sums and checks if it returns to the starting number in exactly cycleLength steps.
45+
*
46+
* @param number the starting number (must be positive)
47+
* @param cycleLength the expected cycle length (must be greater than 1)
48+
* @return true if the number is part of a sociable cycle of given length, false otherwise
49+
*/
50+
public static boolean isSociable(final int number, final int cycleLength) {
51+
if (number <= 0 || cycleLength <= 1) {
52+
return false;
53+
}
54+
int current = number;
55+
for (int i = 0; i < cycleLength; i++) {
56+
current = sumOfProperDivisors(current);
57+
if (current == number && i == cycleLength - 1) {
58+
return true;
59+
}
60+
if (current == number && i != cycleLength - 1) {
61+
return false;
62+
}
63+
}
64+
return false;
65+
}
66+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package com.thealgorithms.maths;
2+
// author: Vraj Prajapati @Rosander0
3+
4+
import static org.junit.jupiter.api.Assertions.assertFalse;
5+
import static org.junit.jupiter.api.Assertions.assertTrue;
6+
7+
import org.junit.jupiter.api.Test;
8+
9+
public class SociableNumberTest {
10+
11+
@Test
12+
public void testSociableCycleOfLengthFive() {
13+
assertTrue(SociableNumber.isSociable(12496, 5));
14+
}
15+
16+
@Test
17+
public void testAmicableNumbersAreSociableOfLengthTwo() {
18+
assertTrue(SociableNumber.isSociable(220, 2));
19+
assertTrue(SociableNumber.isSociable(284, 2));
20+
}
21+
22+
@Test
23+
public void testNonSociableNumbers() {
24+
assertFalse(SociableNumber.isSociable(12, 5));
25+
assertFalse(SociableNumber.isSociable(10, 3));
26+
}
27+
28+
@Test
29+
public void testInvalidInputs() {
30+
assertFalse(SociableNumber.isSociable(0, 5));
31+
assertFalse(SociableNumber.isSociable(-1, 5));
32+
assertFalse(SociableNumber.isSociable(220, 1));
33+
}
34+
}

0 commit comments

Comments
 (0)