diff --git a/src/main/java/com/thealgorithms/maths/LucasSeries.java b/src/main/java/com/thealgorithms/maths/LucasSeries.java index e277c511f317..90a35f0d6259 100644 --- a/src/main/java/com/thealgorithms/maths/LucasSeries.java +++ b/src/main/java/com/thealgorithms/maths/LucasSeries.java @@ -1,38 +1,69 @@ package com.thealgorithms.maths; /** - * https://en.wikipedia.org/wiki/Lucas_number + * Utility class for calculating Lucas numbers. + * The Lucas sequence is similar to the Fibonacci sequence but starts with 2 and + * 1. + * The sequence follows: L(n) = L(n-1) + L(n-2) + * Starting values: L(1) = 2, L(2) = 1 + * Sequence: 2, 1, 3, 4, 7, 11, 18, 29, 47, 76, 123, ... + * + * @see Lucas Number + * @author TheAlgorithms Contributors */ public final class LucasSeries { private LucasSeries() { } /** - * Calculate nth number of Lucas Series(2, 1, 3, 4, 7, 11, 18, 29, 47, 76, - * 123, ....) using recursion + * Calculate the nth Lucas number using recursion. + * Time Complexity: O(2^n) - exponential due to recursive calls + * Space Complexity: O(n) - recursion depth * - * @param n nth - * @return nth number of Lucas Series + * @param n the position in the Lucas sequence (1-indexed, must be positive) + * @return the nth Lucas number + * @throws IllegalArgumentException if n is less than 1 */ public static int lucasSeries(int n) { - return n == 1 ? 2 : n == 2 ? 1 : lucasSeries(n - 1) + lucasSeries(n - 2); + if (n < 1) { + throw new IllegalArgumentException("Input must be a positive integer. Provided: " + n); + } + if (n == 1) { + return 2; + } + if (n == 2) { + return 1; + } + return lucasSeries(n - 1) + lucasSeries(n - 2); } /** - * Calculate nth number of Lucas Series(2, 1, 3, 4, 7, 11, 18, 29, 47, 76, - * 123, ....) using iteration + * Calculate the nth Lucas number using iteration. + * Time Complexity: O(n) - single loop through n iterations + * Space Complexity: O(1) - constant space usage * - * @param n nth - * @return nth number of lucas series + * @param n the position in the Lucas sequence (1-indexed, must be positive) + * @return the nth Lucas number + * @throws IllegalArgumentException if n is less than 1 */ public static int lucasSeriesIteration(int n) { + if (n < 1) { + throw new IllegalArgumentException("Input must be a positive integer. Provided: " + n); + } + if (n == 1) { + return 2; + } + if (n == 2) { + return 1; + } + int previous = 2; int current = 1; - for (int i = 1; i < n; i++) { + for (int i = 2; i < n; i++) { int next = previous + current; previous = current; current = next; } - return previous; + return current; } } diff --git a/src/test/java/com/thealgorithms/maths/LucasSeriesTest.java b/src/test/java/com/thealgorithms/maths/LucasSeriesTest.java index 3576268c5d0c..4b6c1e41ecb6 100644 --- a/src/test/java/com/thealgorithms/maths/LucasSeriesTest.java +++ b/src/test/java/com/thealgorithms/maths/LucasSeriesTest.java @@ -1,28 +1,158 @@ package com.thealgorithms.maths; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; import org.junit.jupiter.api.Test; -public class LucasSeriesTest { +/** + * Test cases for {@link LucasSeries} class. + * Tests both recursive and iterative implementations for correctness, + * edge cases, and error handling. + */ +class LucasSeriesTest { + + /** + * Test the first Lucas number L(1) = 2 + */ @Test - void lucasSeriesTwo() { + void testFirstLucasNumber() { assertEquals(2, LucasSeries.lucasSeries(1)); assertEquals(2, LucasSeries.lucasSeriesIteration(1)); } + + /** + * Test the second Lucas number L(2) = 1 + */ @Test - void lucasSeriesOne() { + void testSecondLucasNumber() { assertEquals(1, LucasSeries.lucasSeries(2)); assertEquals(1, LucasSeries.lucasSeriesIteration(2)); } + + /** + * Test the third Lucas number L(3) = 3 + */ + @Test + void testThirdLucasNumber() { + assertEquals(3, LucasSeries.lucasSeries(3)); + assertEquals(3, LucasSeries.lucasSeriesIteration(3)); + } + + /** + * Test the fourth Lucas number L(4) = 4 + */ @Test - void lucasSeriesSeven() { + void testFourthLucasNumber() { + assertEquals(4, LucasSeries.lucasSeries(4)); + assertEquals(4, LucasSeries.lucasSeriesIteration(4)); + } + + /** + * Test the fifth Lucas number L(5) = 7 + */ + @Test + void testFifthLucasNumber() { assertEquals(7, LucasSeries.lucasSeries(5)); assertEquals(7, LucasSeries.lucasSeriesIteration(5)); } + + /** + * Test the sixth Lucas number L(6) = 11 + */ + @Test + void testSixthLucasNumber() { + assertEquals(11, LucasSeries.lucasSeries(6)); + assertEquals(11, LucasSeries.lucasSeriesIteration(6)); + } + + /** + * Test the seventh Lucas number L(7) = 18 + */ + @Test + void testSeventhLucasNumber() { + assertEquals(18, LucasSeries.lucasSeries(7)); + assertEquals(18, LucasSeries.lucasSeriesIteration(7)); + } + + /** + * Test the eighth Lucas number L(8) = 29 + */ + @Test + void testEighthLucasNumber() { + assertEquals(29, LucasSeries.lucasSeries(8)); + assertEquals(29, LucasSeries.lucasSeriesIteration(8)); + } + + /** + * Test the ninth Lucas number L(9) = 47 + */ @Test - void lucasSeriesEleven() { + void testNinthLucasNumber() { + assertEquals(47, LucasSeries.lucasSeries(9)); + assertEquals(47, LucasSeries.lucasSeriesIteration(9)); + } + + /** + * Test the tenth Lucas number L(10) = 76 + */ + @Test + void testTenthLucasNumber() { + assertEquals(76, LucasSeries.lucasSeries(10)); + assertEquals(76, LucasSeries.lucasSeriesIteration(10)); + } + + /** + * Test the eleventh Lucas number L(11) = 123 + */ + @Test + void testEleventhLucasNumber() { assertEquals(123, LucasSeries.lucasSeries(11)); assertEquals(123, LucasSeries.lucasSeriesIteration(11)); } + + /** + * Test larger Lucas numbers to ensure correctness + */ + @Test + void testLargerLucasNumbers() { + assertEquals(199, LucasSeries.lucasSeries(12)); + assertEquals(199, LucasSeries.lucasSeriesIteration(12)); + assertEquals(322, LucasSeries.lucasSeries(13)); + assertEquals(322, LucasSeries.lucasSeriesIteration(13)); + assertEquals(521, LucasSeries.lucasSeries(14)); + assertEquals(521, LucasSeries.lucasSeriesIteration(14)); + assertEquals(843, LucasSeries.lucasSeries(15)); + assertEquals(843, LucasSeries.lucasSeriesIteration(15)); + } + + /** + * Test that both methods produce the same results + */ + @Test + void testRecursiveAndIterativeConsistency() { + for (int i = 1; i <= 15; i++) { + assertEquals(LucasSeries.lucasSeries(i), LucasSeries.lucasSeriesIteration(i), "Mismatch at position " + i); + } + } + + /** + * Test invalid input: zero + */ + @Test + void testZeroInputThrowsException() { + assertThrows(IllegalArgumentException.class, () -> LucasSeries.lucasSeries(0)); + assertThrows(IllegalArgumentException.class, () -> LucasSeries.lucasSeriesIteration(0)); + } + + /** + * Test invalid input: negative number + */ + @Test + void testNegativeInputThrowsException() { + assertThrows(IllegalArgumentException.class, () -> LucasSeries.lucasSeries(-1)); + assertThrows(IllegalArgumentException.class, () -> LucasSeries.lucasSeriesIteration(-1)); + assertThrows(IllegalArgumentException.class, () -> LucasSeries.lucasSeries(-5)); + assertThrows(IllegalArgumentException.class, () -> LucasSeries.lucasSeriesIteration(-5)); + } }