mirror of
https://github.com/TheAlgorithms/Java.git
synced 2025-12-19 07:00:35 +08:00
refactor: Enhance docs, code, add tests in KaprekarNumbers (#6747)
Co-authored-by: a <alexanderklmn@gmail.com>
This commit is contained in:
@@ -4,23 +4,51 @@ import java.math.BigInteger;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Utility class for identifying and working with Kaprekar Numbers.
|
||||
* <p>
|
||||
* A Kaprekar number is a positive integer with the following property:
|
||||
* If you square it, then split the resulting number into two parts (right part
|
||||
* has same number of
|
||||
* digits as the original number, left part has the remaining digits), and
|
||||
* finally add the two
|
||||
* parts together, you get the original number.
|
||||
* <p>
|
||||
* For example:
|
||||
* <ul>
|
||||
* <li>9: 9² = 81 → 8 + 1 = 9 (Kaprekar number)</li>
|
||||
* <li>45: 45² = 2025 → 20 + 25 = 45 (Kaprekar number)</li>
|
||||
* <li>297: 297² = 88209 → 88 + 209 = 297 (Kaprekar number)</li>
|
||||
* </ul>
|
||||
* <p>
|
||||
* Note: The right part can have leading zeros, but must not be all zeros.
|
||||
*
|
||||
* @see <a href="https://en.wikipedia.org/wiki/Kaprekar_number">Kaprekar Number
|
||||
* - Wikipedia</a>
|
||||
* @author TheAlgorithms (https://github.com/TheAlgorithms)
|
||||
*/
|
||||
public final class KaprekarNumbers {
|
||||
private KaprekarNumbers() {
|
||||
}
|
||||
|
||||
/* This program demonstrates if a given number is Kaprekar Number or not.
|
||||
Kaprekar Number: A Kaprekar number is an n-digit number which its square can be split into
|
||||
two parts where the right part has n digits and sum of these parts is equal to the original
|
||||
number. */
|
||||
|
||||
// Provides a list of kaprekarNumber in a range
|
||||
public static List<Long> kaprekarNumberInRange(long start, long end) throws Exception {
|
||||
long n = end - start;
|
||||
if (n < 0) {
|
||||
throw new Exception("Invalid range");
|
||||
/**
|
||||
* Finds all Kaprekar numbers within a given range (inclusive).
|
||||
*
|
||||
* @param start the starting number of the range (inclusive)
|
||||
* @param end the ending number of the range (inclusive)
|
||||
* @return a list of all Kaprekar numbers in the specified range
|
||||
* @throws IllegalArgumentException if start is greater than end or if start is
|
||||
* negative
|
||||
*/
|
||||
public static List<Long> kaprekarNumberInRange(long start, long end) {
|
||||
if (start > end) {
|
||||
throw new IllegalArgumentException("Start must be less than or equal to end. Given start: " + start + ", end: " + end);
|
||||
}
|
||||
if (start < 0) {
|
||||
throw new IllegalArgumentException("Start must be non-negative. Given start: " + start);
|
||||
}
|
||||
ArrayList<Long> list = new ArrayList<>();
|
||||
|
||||
ArrayList<Long> list = new ArrayList<>();
|
||||
for (long i = start; i <= end; i++) {
|
||||
if (isKaprekarNumber(i)) {
|
||||
list.add(i);
|
||||
@@ -30,24 +58,60 @@ public final class KaprekarNumbers {
|
||||
return list;
|
||||
}
|
||||
|
||||
// Checks whether a given number is Kaprekar Number or not
|
||||
/**
|
||||
* Checks whether a given number is a Kaprekar number.
|
||||
* <p>
|
||||
* The algorithm works as follows:
|
||||
* <ol>
|
||||
* <li>Square the number</li>
|
||||
* <li>Split the squared number into two parts: left and right</li>
|
||||
* <li>The right part has the same number of digits as the original number</li>
|
||||
* <li>Add the left and right parts</li>
|
||||
* <li>If the sum equals the original number, it's a Kaprekar number</li>
|
||||
* </ol>
|
||||
* <p>
|
||||
* Special handling is required for numbers whose squares contain zeros.
|
||||
*
|
||||
* @param num the number to check
|
||||
* @return true if the number is a Kaprekar number, false otherwise
|
||||
* @throws IllegalArgumentException if num is negative
|
||||
*/
|
||||
public static boolean isKaprekarNumber(long num) {
|
||||
if (num < 0) {
|
||||
throw new IllegalArgumentException("Number must be non-negative. Given: " + num);
|
||||
}
|
||||
|
||||
if (num == 0 || num == 1) {
|
||||
return true;
|
||||
}
|
||||
|
||||
String number = Long.toString(num);
|
||||
BigInteger originalNumber = BigInteger.valueOf(num);
|
||||
BigInteger numberSquared = originalNumber.multiply(originalNumber);
|
||||
if (number.length() == numberSquared.toString().length()) {
|
||||
return number.equals(numberSquared.toString());
|
||||
} else {
|
||||
BigInteger leftDigits1 = BigInteger.ZERO;
|
||||
BigInteger leftDigits2;
|
||||
if (numberSquared.toString().contains("0")) {
|
||||
leftDigits1 = new BigInteger(numberSquared.toString().substring(0, numberSquared.toString().indexOf("0")));
|
||||
}
|
||||
leftDigits2 = new BigInteger(numberSquared.toString().substring(0, (numberSquared.toString().length() - number.length())));
|
||||
BigInteger rightDigits = new BigInteger(numberSquared.toString().substring(numberSquared.toString().length() - number.length()));
|
||||
String x = leftDigits1.add(rightDigits).toString();
|
||||
String y = leftDigits2.add(rightDigits).toString();
|
||||
return (number.equals(x)) || (number.equals(y));
|
||||
String squaredStr = numberSquared.toString();
|
||||
|
||||
// Special case: if the squared number has the same length as the original
|
||||
if (number.length() == squaredStr.length()) {
|
||||
return number.equals(squaredStr);
|
||||
}
|
||||
|
||||
// Calculate the split position
|
||||
int splitPos = squaredStr.length() - number.length();
|
||||
|
||||
// Split the squared number into left and right parts
|
||||
String leftPart = squaredStr.substring(0, splitPos);
|
||||
String rightPart = squaredStr.substring(splitPos);
|
||||
|
||||
// Parse the parts as BigInteger (handles empty left part as zero)
|
||||
BigInteger leftNum = leftPart.isEmpty() ? BigInteger.ZERO : new BigInteger(leftPart);
|
||||
BigInteger rightNum = new BigInteger(rightPart);
|
||||
|
||||
// Check if right part is all zeros (invalid for Kaprekar numbers except 1)
|
||||
if (rightNum.equals(BigInteger.ZERO)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if the sum equals the original number
|
||||
return leftNum.add(rightNum).equals(originalNumber);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user