Dev: Added algorithm to find the nth number in the Sylvester Sequence (#6613)

Added algorithm to find the nth number in the SylvesterSequence
This commit is contained in:
Banula Kumarage
2025-10-04 19:26:08 +05:30
committed by GitHub
parent 6d5170999a
commit a0b6c52790
2 changed files with 101 additions and 0 deletions

View File

@@ -0,0 +1,50 @@
package com.thealgorithms.recursion;
import java.math.BigInteger;
/**
* A utility class for calculating numbers in Sylvester's sequence.
*
* <p>Sylvester's sequence is a sequence of integers where each term is calculated
* using the formula:
* <pre>
* a(n) = a(n-1) * (a(n-1) - 1) + 1
* </pre>
* with the first term being 2.
*
* <p>This class is final and cannot be instantiated.
*
* @see <a href="https://en.wikipedia.org/wiki/Sylvester_sequence">Wikipedia: Sylvester sequence</a>
*/
public final class SylvesterSequence {
// Private constructor to prevent instantiation
private SylvesterSequence() {
}
/**
* Calculates the nth number in Sylvester's sequence.
*
* <p>The sequence is defined recursively, with the first term being 2:
* <pre>
* a(1) = 2
* a(n) = a(n-1) * (a(n-1) - 1) + 1 for n > 1
* </pre>
*
* @param n the position in the sequence (must be greater than 0)
* @return the nth number in Sylvester's sequence
* @throws IllegalArgumentException if n is less than or equal to 0
*/
public static BigInteger sylvester(int n) {
if (n <= 0) {
throw new IllegalArgumentException("sylvester() does not accept negative numbers or zero.");
}
if (n == 1) {
return BigInteger.valueOf(2);
} else {
BigInteger prev = sylvester(n - 1);
// Sylvester sequence formula: a(n) = a(n-1) * (a(n-1) - 1) + 1
return prev.multiply(prev.subtract(BigInteger.ONE)).add(BigInteger.ONE);
}
}
}

View File

@@ -0,0 +1,51 @@
package com.thealgorithms.recursion;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import java.math.BigInteger;
import java.util.stream.Stream;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;
import org.junit.jupiter.params.provider.ValueSource;
class SylvesterSequenceTest {
/**
* Provides test cases for valid Sylvester sequence numbers.
* Format: { n, expectedValue }
*/
static Stream<Object[]> validSylvesterNumbers() {
return Stream.of(new Object[] {1, BigInteger.valueOf(2)}, new Object[] {2, BigInteger.valueOf(3)}, new Object[] {3, BigInteger.valueOf(7)}, new Object[] {4, BigInteger.valueOf(43)}, new Object[] {5, BigInteger.valueOf(1807)}, new Object[] {6, new BigInteger("3263443")},
new Object[] {7, new BigInteger("10650056950807")}, new Object[] {8, new BigInteger("113423713055421844361000443")});
}
@ParameterizedTest
@MethodSource("validSylvesterNumbers")
void testSylvesterValidNumbers(int n, BigInteger expected) {
assertEquals(expected, SylvesterSequence.sylvester(n), "Sylvester sequence value mismatch for n=" + n);
}
/**
* Test edge case for n <= 0 which should throw IllegalArgumentException
*/
@ParameterizedTest
@ValueSource(ints = {0, -1, -10, -100})
void testSylvesterInvalidZero(int n) {
assertThrows(IllegalArgumentException.class, () -> SylvesterSequence.sylvester(n));
}
/**
* Test a larger number to ensure no overflow occurs.
*/
@Test
void testSylvesterLargeNumber() {
int n = 10;
BigInteger result = SylvesterSequence.sylvester(n);
assertNotNull(result);
assertTrue(result.compareTo(BigInteger.ZERO) > 0, "Result should be positive");
}
}