Skip to content

Commit c6497a2

Browse files
authored
refactor: Enhance docs, code, add tests in LucasSeries (#6749)
1 parent f460c60 commit c6497a2

File tree

2 files changed

+178
-17
lines changed

2 files changed

+178
-17
lines changed
Lines changed: 43 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,69 @@
11
package com.thealgorithms.maths;
22

33
/**
4-
* https://en.wikipedia.org/wiki/Lucas_number
4+
* Utility class for calculating Lucas numbers.
5+
* The Lucas sequence is similar to the Fibonacci sequence but starts with 2 and
6+
* 1.
7+
* The sequence follows: L(n) = L(n-1) + L(n-2)
8+
* Starting values: L(1) = 2, L(2) = 1
9+
* Sequence: 2, 1, 3, 4, 7, 11, 18, 29, 47, 76, 123, ...
10+
*
11+
* @see <a href="https://en.wikipedia.org/wiki/Lucas_number">Lucas Number</a>
12+
* @author TheAlgorithms Contributors
513
*/
614
public final class LucasSeries {
715
private LucasSeries() {
816
}
917

1018
/**
11-
* Calculate nth number of Lucas Series(2, 1, 3, 4, 7, 11, 18, 29, 47, 76,
12-
* 123, ....) using recursion
19+
* Calculate the nth Lucas number using recursion.
20+
* Time Complexity: O(2^n) - exponential due to recursive calls
21+
* Space Complexity: O(n) - recursion depth
1322
*
14-
* @param n nth
15-
* @return nth number of Lucas Series
23+
* @param n the position in the Lucas sequence (1-indexed, must be positive)
24+
* @return the nth Lucas number
25+
* @throws IllegalArgumentException if n is less than 1
1626
*/
1727
public static int lucasSeries(int n) {
18-
return n == 1 ? 2 : n == 2 ? 1 : lucasSeries(n - 1) + lucasSeries(n - 2);
28+
if (n < 1) {
29+
throw new IllegalArgumentException("Input must be a positive integer. Provided: " + n);
30+
}
31+
if (n == 1) {
32+
return 2;
33+
}
34+
if (n == 2) {
35+
return 1;
36+
}
37+
return lucasSeries(n - 1) + lucasSeries(n - 2);
1938
}
2039

2140
/**
22-
* Calculate nth number of Lucas Series(2, 1, 3, 4, 7, 11, 18, 29, 47, 76,
23-
* 123, ....) using iteration
41+
* Calculate the nth Lucas number using iteration.
42+
* Time Complexity: O(n) - single loop through n iterations
43+
* Space Complexity: O(1) - constant space usage
2444
*
25-
* @param n nth
26-
* @return nth number of lucas series
45+
* @param n the position in the Lucas sequence (1-indexed, must be positive)
46+
* @return the nth Lucas number
47+
* @throws IllegalArgumentException if n is less than 1
2748
*/
2849
public static int lucasSeriesIteration(int n) {
50+
if (n < 1) {
51+
throw new IllegalArgumentException("Input must be a positive integer. Provided: " + n);
52+
}
53+
if (n == 1) {
54+
return 2;
55+
}
56+
if (n == 2) {
57+
return 1;
58+
}
59+
2960
int previous = 2;
3061
int current = 1;
31-
for (int i = 1; i < n; i++) {
62+
for (int i = 2; i < n; i++) {
3263
int next = previous + current;
3364
previous = current;
3465
current = next;
3566
}
36-
return previous;
67+
return current;
3768
}
3869
}
Lines changed: 135 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,158 @@
11
package com.thealgorithms.maths;
22

33
import static org.junit.jupiter.api.Assertions.assertEquals;
4+
import static org.junit.jupiter.api.Assertions.assertThrows;
45

56
import org.junit.jupiter.api.Test;
67

7-
public class LucasSeriesTest {
8+
/**
9+
* Test cases for {@link LucasSeries} class.
10+
* Tests both recursive and iterative implementations for correctness,
11+
* edge cases, and error handling.
12+
*/
13+
class LucasSeriesTest {
14+
15+
/**
16+
* Test the first Lucas number L(1) = 2
17+
*/
818
@Test
9-
void lucasSeriesTwo() {
19+
void testFirstLucasNumber() {
1020
assertEquals(2, LucasSeries.lucasSeries(1));
1121
assertEquals(2, LucasSeries.lucasSeriesIteration(1));
1222
}
23+
24+
/**
25+
* Test the second Lucas number L(2) = 1
26+
*/
1327
@Test
14-
void lucasSeriesOne() {
28+
void testSecondLucasNumber() {
1529
assertEquals(1, LucasSeries.lucasSeries(2));
1630
assertEquals(1, LucasSeries.lucasSeriesIteration(2));
1731
}
32+
33+
/**
34+
* Test the third Lucas number L(3) = 3
35+
*/
36+
@Test
37+
void testThirdLucasNumber() {
38+
assertEquals(3, LucasSeries.lucasSeries(3));
39+
assertEquals(3, LucasSeries.lucasSeriesIteration(3));
40+
}
41+
42+
/**
43+
* Test the fourth Lucas number L(4) = 4
44+
*/
1845
@Test
19-
void lucasSeriesSeven() {
46+
void testFourthLucasNumber() {
47+
assertEquals(4, LucasSeries.lucasSeries(4));
48+
assertEquals(4, LucasSeries.lucasSeriesIteration(4));
49+
}
50+
51+
/**
52+
* Test the fifth Lucas number L(5) = 7
53+
*/
54+
@Test
55+
void testFifthLucasNumber() {
2056
assertEquals(7, LucasSeries.lucasSeries(5));
2157
assertEquals(7, LucasSeries.lucasSeriesIteration(5));
2258
}
59+
60+
/**
61+
* Test the sixth Lucas number L(6) = 11
62+
*/
63+
@Test
64+
void testSixthLucasNumber() {
65+
assertEquals(11, LucasSeries.lucasSeries(6));
66+
assertEquals(11, LucasSeries.lucasSeriesIteration(6));
67+
}
68+
69+
/**
70+
* Test the seventh Lucas number L(7) = 18
71+
*/
72+
@Test
73+
void testSeventhLucasNumber() {
74+
assertEquals(18, LucasSeries.lucasSeries(7));
75+
assertEquals(18, LucasSeries.lucasSeriesIteration(7));
76+
}
77+
78+
/**
79+
* Test the eighth Lucas number L(8) = 29
80+
*/
81+
@Test
82+
void testEighthLucasNumber() {
83+
assertEquals(29, LucasSeries.lucasSeries(8));
84+
assertEquals(29, LucasSeries.lucasSeriesIteration(8));
85+
}
86+
87+
/**
88+
* Test the ninth Lucas number L(9) = 47
89+
*/
2390
@Test
24-
void lucasSeriesEleven() {
91+
void testNinthLucasNumber() {
92+
assertEquals(47, LucasSeries.lucasSeries(9));
93+
assertEquals(47, LucasSeries.lucasSeriesIteration(9));
94+
}
95+
96+
/**
97+
* Test the tenth Lucas number L(10) = 76
98+
*/
99+
@Test
100+
void testTenthLucasNumber() {
101+
assertEquals(76, LucasSeries.lucasSeries(10));
102+
assertEquals(76, LucasSeries.lucasSeriesIteration(10));
103+
}
104+
105+
/**
106+
* Test the eleventh Lucas number L(11) = 123
107+
*/
108+
@Test
109+
void testEleventhLucasNumber() {
25110
assertEquals(123, LucasSeries.lucasSeries(11));
26111
assertEquals(123, LucasSeries.lucasSeriesIteration(11));
27112
}
113+
114+
/**
115+
* Test larger Lucas numbers to ensure correctness
116+
*/
117+
@Test
118+
void testLargerLucasNumbers() {
119+
assertEquals(199, LucasSeries.lucasSeries(12));
120+
assertEquals(199, LucasSeries.lucasSeriesIteration(12));
121+
assertEquals(322, LucasSeries.lucasSeries(13));
122+
assertEquals(322, LucasSeries.lucasSeriesIteration(13));
123+
assertEquals(521, LucasSeries.lucasSeries(14));
124+
assertEquals(521, LucasSeries.lucasSeriesIteration(14));
125+
assertEquals(843, LucasSeries.lucasSeries(15));
126+
assertEquals(843, LucasSeries.lucasSeriesIteration(15));
127+
}
128+
129+
/**
130+
* Test that both methods produce the same results
131+
*/
132+
@Test
133+
void testRecursiveAndIterativeConsistency() {
134+
for (int i = 1; i <= 15; i++) {
135+
assertEquals(LucasSeries.lucasSeries(i), LucasSeries.lucasSeriesIteration(i), "Mismatch at position " + i);
136+
}
137+
}
138+
139+
/**
140+
* Test invalid input: zero
141+
*/
142+
@Test
143+
void testZeroInputThrowsException() {
144+
assertThrows(IllegalArgumentException.class, () -> LucasSeries.lucasSeries(0));
145+
assertThrows(IllegalArgumentException.class, () -> LucasSeries.lucasSeriesIteration(0));
146+
}
147+
148+
/**
149+
* Test invalid input: negative number
150+
*/
151+
@Test
152+
void testNegativeInputThrowsException() {
153+
assertThrows(IllegalArgumentException.class, () -> LucasSeries.lucasSeries(-1));
154+
assertThrows(IllegalArgumentException.class, () -> LucasSeries.lucasSeriesIteration(-1));
155+
assertThrows(IllegalArgumentException.class, () -> LucasSeries.lucasSeries(-5));
156+
assertThrows(IllegalArgumentException.class, () -> LucasSeries.lucasSeriesIteration(-5));
157+
}
28158
}

0 commit comments

Comments
 (0)