diff --git a/src/main/java/com/thealgorithms/maths/KeithNumber.java b/src/main/java/com/thealgorithms/maths/KeithNumber.java
index 1756cfbae91b..eb7f800d378f 100644
--- a/src/main/java/com/thealgorithms/maths/KeithNumber.java
+++ b/src/main/java/com/thealgorithms/maths/KeithNumber.java
@@ -4,57 +4,98 @@
import java.util.Collections;
import java.util.Scanner;
-final class KeithNumber {
+/**
+ * A Keith number is an n-digit positive integer where the sequence formed by
+ * starting with its digits and repeatedly adding the previous n terms,
+ * eventually reaches the number itself.
+ *
+ *
+ * For example:
+ *
+ * - 14 is a Keith number: 1, 4, 5, 9, 14
+ * - 19 is a Keith number: 1, 9, 10, 19
+ * - 28 is a Keith number: 2, 8, 10, 18, 28
+ * - 197 is a Keith number: 1, 9, 7, 17, 33, 57, 107, 197
+ *
+ *
+ * @see Keith Number -
+ * Wikipedia
+ * @see Keith Number -
+ * MathWorld
+ */
+public final class KeithNumber {
private KeithNumber() {
}
- // user-defined function that checks if the given number is Keith or not
- static boolean isKeith(int x) {
- // List stores all the digits of the X
+ /**
+ * Checks if a given number is a Keith number.
+ *
+ *
+ * The algorithm works as follows:
+ *
+ * - Extract all digits of the number and store them in a list
+ * - Generate subsequent terms by summing the last n digits
+ * - Continue until a term equals or exceeds the original number
+ * - If a term equals the number, it is a Keith number
+ *
+ *
+ * @param number the number to check (must be positive)
+ * @return {@code true} if the number is a Keith number, {@code false} otherwise
+ * @throws IllegalArgumentException if the number is not positive
+ */
+ public static boolean isKeith(int number) {
+ if (number <= 0) {
+ throw new IllegalArgumentException("Number must be positive");
+ }
+
+ // Extract digits and store them in the list
ArrayList terms = new ArrayList<>();
- // n denotes the number of digits
- int temp = x;
- int n = 0;
- // executes until the condition becomes false
+ int temp = number;
+ int digitCount = 0;
+
while (temp > 0) {
- // determines the last digit of the number and add it to the List
terms.add(temp % 10);
- // removes the last digit
temp = temp / 10;
- // increments the number of digits (n) by 1
- n++;
+ digitCount++;
}
- // reverse the List
+
+ // Reverse the list to get digits in correct order
Collections.reverse(terms);
+
+ // Generate subsequent terms in the sequence
int nextTerm = 0;
- int i = n;
- // finds next term for the series
- // loop executes until the condition returns true
- while (nextTerm < x) {
+ int currentIndex = digitCount;
+
+ while (nextTerm < number) {
nextTerm = 0;
- // next term is the sum of previous n terms (it depends on number of digits the number
- // has)
- for (int j = 1; j <= n; j++) {
- nextTerm = nextTerm + terms.get(i - j);
+ // Sum the last 'digitCount' terms
+ for (int j = 1; j <= digitCount; j++) {
+ nextTerm = nextTerm + terms.get(currentIndex - j);
}
terms.add(nextTerm);
- i++;
+ currentIndex++;
}
- // when the control comes out of the while loop, there will be two conditions:
- // either nextTerm will be equal to x or greater than x
- // if equal, the given number is Keith, else not
- return (nextTerm == x);
+
+ // Check if the generated term equals the original number
+ return (nextTerm == number);
}
- // driver code
+ /**
+ * Main method for demonstrating Keith number detection.
+ * Reads a number from standard input and checks if it is a Keith number.
+ *
+ * @param args command line arguments (not used)
+ */
public static void main(String[] args) {
- Scanner in = new Scanner(System.in);
- int n = in.nextInt();
- if (isKeith(n)) {
- System.out.println("Yes, the given number is a Keith number.");
+ Scanner scanner = new Scanner(System.in);
+ System.out.print("Enter a positive integer: ");
+ int number = scanner.nextInt();
+
+ if (isKeith(number)) {
+ System.out.println("Yes, " + number + " is a Keith number.");
} else {
- System.out.println("No, the given number is not a Keith number.");
+ System.out.println("No, " + number + " is not a Keith number.");
}
- in.close();
+ scanner.close();
}
}
diff --git a/src/test/java/com/thealgorithms/maths/KeithNumberTest.java b/src/test/java/com/thealgorithms/maths/KeithNumberTest.java
new file mode 100644
index 000000000000..cac6b925e5c1
--- /dev/null
+++ b/src/test/java/com/thealgorithms/maths/KeithNumberTest.java
@@ -0,0 +1,153 @@
+package com.thealgorithms.maths;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import org.junit.jupiter.api.Test;
+
+/**
+ * Test cases for {@link KeithNumber}.
+ */
+class KeithNumberTest {
+
+ /**
+ * Tests single-digit Keith numbers.
+ * All single-digit numbers (1-9) are Keith numbers by definition.
+ */
+ @Test
+ void testSingleDigitKeithNumbers() {
+ assertTrue(KeithNumber.isKeith(1));
+ assertTrue(KeithNumber.isKeith(2));
+ assertTrue(KeithNumber.isKeith(3));
+ assertTrue(KeithNumber.isKeith(4));
+ assertTrue(KeithNumber.isKeith(5));
+ assertTrue(KeithNumber.isKeith(6));
+ assertTrue(KeithNumber.isKeith(7));
+ assertTrue(KeithNumber.isKeith(8));
+ assertTrue(KeithNumber.isKeith(9));
+ }
+
+ /**
+ * Tests two-digit Keith numbers.
+ * Known two-digit Keith numbers: 14, 19, 28, 47, 61, 75.
+ */
+ @Test
+ void testTwoDigitKeithNumbers() {
+ assertTrue(KeithNumber.isKeith(14));
+ assertTrue(KeithNumber.isKeith(19));
+ assertTrue(KeithNumber.isKeith(28));
+ assertTrue(KeithNumber.isKeith(47));
+ assertTrue(KeithNumber.isKeith(61));
+ assertTrue(KeithNumber.isKeith(75));
+ }
+
+ /**
+ * Tests three-digit Keith numbers.
+ * Known three-digit Keith numbers: 197, 742.
+ */
+ @Test
+ void testThreeDigitKeithNumbers() {
+ assertTrue(KeithNumber.isKeith(197));
+ assertTrue(KeithNumber.isKeith(742));
+ }
+
+ /**
+ * Tests four-digit Keith numbers.
+ * Known four-digit Keith numbers: 1104, 1537, 2208, 2580, 3684, 4788, 7385,
+ * 7647, 7909.
+ */
+ @Test
+ void testFourDigitKeithNumbers() {
+ assertTrue(KeithNumber.isKeith(1104));
+ assertTrue(KeithNumber.isKeith(1537));
+ assertTrue(KeithNumber.isKeith(2208));
+ }
+
+ /**
+ * Tests two-digit non-Keith numbers.
+ */
+ @Test
+ void testTwoDigitNonKeithNumbers() {
+ assertFalse(KeithNumber.isKeith(10));
+ assertFalse(KeithNumber.isKeith(11));
+ assertFalse(KeithNumber.isKeith(12));
+ assertFalse(KeithNumber.isKeith(13));
+ assertFalse(KeithNumber.isKeith(15));
+ assertFalse(KeithNumber.isKeith(20));
+ assertFalse(KeithNumber.isKeith(30));
+ assertFalse(KeithNumber.isKeith(50));
+ }
+
+ /**
+ * Tests three-digit non-Keith numbers.
+ */
+ @Test
+ void testThreeDigitNonKeithNumbers() {
+ assertFalse(KeithNumber.isKeith(100));
+ assertFalse(KeithNumber.isKeith(123));
+ assertFalse(KeithNumber.isKeith(196));
+ assertFalse(KeithNumber.isKeith(198));
+ assertFalse(KeithNumber.isKeith(456));
+ assertFalse(KeithNumber.isKeith(741));
+ assertFalse(KeithNumber.isKeith(743));
+ assertFalse(KeithNumber.isKeith(999));
+ }
+
+ /**
+ * Tests validation for edge case 14 in detail.
+ * 14 is a Keith number: 1, 4, 5 (1+4), 9 (4+5), 14 (5+9).
+ */
+ @Test
+ void testKeithNumber14() {
+ assertTrue(KeithNumber.isKeith(14));
+ }
+
+ /**
+ * Tests validation for edge case 197 in detail.
+ * 197 is a Keith number: 1, 9, 7, 17, 33, 57, 107, 197.
+ */
+ @Test
+ void testKeithNumber197() {
+ assertTrue(KeithNumber.isKeith(197));
+ }
+
+ /**
+ * Tests that zero throws an IllegalArgumentException.
+ */
+ @Test
+ void testZeroThrowsException() {
+ assertThrows(IllegalArgumentException.class, () -> KeithNumber.isKeith(0));
+ }
+
+ /**
+ * Tests that negative numbers throw an IllegalArgumentException.
+ */
+ @Test
+ void testNegativeNumbersThrowException() {
+ assertThrows(IllegalArgumentException.class, () -> KeithNumber.isKeith(-1));
+ assertThrows(IllegalArgumentException.class, () -> KeithNumber.isKeith(-14));
+ assertThrows(IllegalArgumentException.class, () -> KeithNumber.isKeith(-100));
+ }
+
+ /**
+ * Tests various edge cases with larger numbers.
+ */
+ @Test
+ void testLargerNumbers() {
+ assertTrue(KeithNumber.isKeith(2208));
+ assertFalse(KeithNumber.isKeith(2207));
+ assertFalse(KeithNumber.isKeith(2209));
+ }
+
+ /**
+ * Tests the expected behavior with all two-digit Keith numbers.
+ */
+ @Test
+ void testAllKnownTwoDigitKeithNumbers() {
+ int[] knownKeithNumbers = {14, 19, 28, 47, 61, 75};
+ for (int number : knownKeithNumbers) {
+ assertTrue(KeithNumber.isKeith(number), "Expected " + number + " to be a Keith number");
+ }
+ }
+}