Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -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);
}
}
}
Original file line number Diff line number Diff line change
@@ -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");
}
}