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
55 changes: 43 additions & 12 deletions src/main/java/com/thealgorithms/maths/LucasSeries.java
Original file line number Diff line number Diff line change
@@ -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 <a href="https://en.wikipedia.org/wiki/Lucas_number">Lucas Number</a>
* @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;
}
}
140 changes: 135 additions & 5 deletions src/test/java/com/thealgorithms/maths/LucasSeriesTest.java
Original file line number Diff line number Diff line change
@@ -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));
}
}