Skip to content

Commit 88cfec9

Browse files
added program for lucky number
1 parent a4cf6e3 commit 88cfec9

File tree

2 files changed

+104
-0
lines changed

2 files changed

+104
-0
lines changed
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
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) return true;
27+
28+
// If number is eliminated in this step, it's not lucky
29+
if (n % counter == 0) return false;
30+
31+
// Calculate new position after removing every counter-th number
32+
int newNumber = n - (n / counter);
33+
34+
// Recursive call for next round
35+
return isLuckyRecursiveApproach(newNumber, counter + 1);
36+
}
37+
38+
/**
39+
* Check if {@code number} is a Lucky number or not using recursive approach
40+
*
41+
* @param number the number
42+
* @return {@code true} if {@code number} is a Lucky number, otherwise false
43+
*/
44+
public static boolean isLuckyNumber(int number) {
45+
validatePositiveNumber(number);
46+
int counterStarting = 2;
47+
return isLuckyRecursiveApproach(number, counterStarting);
48+
}
49+
50+
/**
51+
* Check if {@code number} is a Lucky number or not using iterative approach
52+
*
53+
* @param number the number
54+
* @return {@code true} if {@code number} is a Lucky number, otherwise false
55+
*/
56+
public static boolean isLucky(int number) {
57+
validatePositiveNumber(number);
58+
59+
int counter = 2; // Position starts from 2 (since first elimination happens at 2)
60+
int position = number; // The position of the number in the sequence
61+
62+
while (counter <= position) {
63+
if (position % counter == 0) return false; // Number is eliminated
64+
65+
// Update the position of n after removing every counter-th number
66+
position = position - (position / counter);
67+
counter++;
68+
}
69+
70+
return true; // Survives all eliminations → Lucky Number
71+
}
72+
}
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)