Skip to content

Commit 9f070b3

Browse files
added program for lucky number
1 parent a4cf6e3 commit 9f070b3

File tree

2 files changed

+110
-0
lines changed

2 files changed

+110
-0
lines changed
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
package com.thealgorithms.maths;
2+
3+
/**
4+
* In number theory, a lucky number is a natural number in a set which is generated by a certain "sieve".
5+
* This sieve is similar to the sieve of Eratosthenes that generates the primes,
6+
* but it eliminates numbers based on their position in the remaining set,
7+
* instead of their value (or position in the initial set of natural numbers).
8+
*
9+
* Wiki: https://en.wikipedia.org/wiki/Lucky_number
10+
*/
11+
public final class LuckyNumber {
12+
13+
private LuckyNumber() {
14+
}
15+
16+
// Common validation method
17+
private static void validatePositiveNumber(int number) {
18+
if (number <= 0) {
19+
throw new IllegalArgumentException("Number must be positive.");
20+
}
21+
}
22+
23+
// Function to check recursively for Lucky Number
24+
private static boolean isLuckyRecursiveApproach(int n, int counter) {
25+
// Base case: If counter exceeds n, number is lucky
26+
if (counter > n) {
27+
return true;
28+
}
29+
30+
// If number is eliminated in this step, it's not lucky
31+
if (n % counter == 0) {
32+
return false;
33+
}
34+
35+
// Calculate new position after removing every counter-th number
36+
int newNumber = n - (n / counter);
37+
38+
// Recursive call for next round
39+
return isLuckyRecursiveApproach(newNumber, counter + 1);
40+
}
41+
42+
/**
43+
* Check if {@code number} is a Lucky number or not using recursive approach
44+
*
45+
* @param number the number
46+
* @return {@code true} if {@code number} is a Lucky number, otherwise false
47+
*/
48+
public static boolean isLuckyNumber(int number) {
49+
validatePositiveNumber(number);
50+
int counterStarting = 2;
51+
return isLuckyRecursiveApproach(number, counterStarting);
52+
}
53+
54+
/**
55+
* Check if {@code number} is a Lucky number or not using iterative approach
56+
*
57+
* @param number the number
58+
* @return {@code true} if {@code number} is a Lucky number, otherwise false
59+
*/
60+
public static boolean isLucky(int number) {
61+
validatePositiveNumber(number);
62+
63+
int counter = 2; // Position starts from 2 (since first elimination happens at 2)
64+
int position = number; // The position of the number in the sequence
65+
66+
while (counter <= position) {
67+
if (position % counter == 0) {
68+
return false;
69+
} // Number is eliminated
70+
71+
// Update the position of n after removing every counter-th number
72+
position = position - (position / counter);
73+
counter++;
74+
}
75+
76+
return true; // Survives all eliminations → Lucky Number
77+
}
78+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package com.thealgorithms.maths;
2+
3+
import static org.junit.jupiter.api.Assertions.assertFalse;
4+
import static org.junit.jupiter.api.Assertions.assertThrows;
5+
import static org.junit.jupiter.api.Assertions.assertTrue;
6+
7+
import org.junit.jupiter.params.ParameterizedTest;
8+
import org.junit.jupiter.params.provider.CsvSource;
9+
10+
class LuckyNumberTest {
11+
12+
@ParameterizedTest
13+
@CsvSource({"1", "3", "13", "49", "109", "459", "949"})
14+
void luckyNumbersTest(int n) {
15+
assertTrue(LuckyNumber.isLucky(n));
16+
assertTrue(LuckyNumber.isLuckyNumber(n));
17+
}
18+
19+
@ParameterizedTest
20+
@CsvSource({"2", "17", "100", "300", "700"})
21+
void nonLuckyNumbersTest(int n) {
22+
assertFalse(LuckyNumber.isLucky(n));
23+
assertFalse(LuckyNumber.isLuckyNumber(n));
24+
}
25+
26+
@ParameterizedTest
27+
@CsvSource({"0", "-1"})
28+
void throwsNegativeNumbersNotAllowed(int n) {
29+
assertThrows(IllegalArgumentException.class, () -> LuckyNumber.isLucky(n));
30+
assertThrows(IllegalArgumentException.class, () -> LuckyNumber.isLuckyNumber(n));
31+
}
32+
}

0 commit comments

Comments
 (0)