Java中的神秘数字6174 [Kaprekar定理]

时间:2016-11-10 07:28:54

标签: java algorithm math

1949年,数学家D. R. Kaprekar设计了一个现在被称为Kaprekar操作的过程。首先选择一个四位数字,其中数字不完全相同(不是1111,2222,...)。然后重新排列数字以获得这些数字可以生成的最大和最小数字。最后,从最大的数字中减去最小的数字以获得新的数字,并对每个新数字继续重复操作。

  

让我们尝试一下,从数字2005开始,最后的数字   年。我们用这些数字可以达到的最大数量是5200,和   最小值为0025或25(如果一个或多个数字为零,则嵌入   这些在最小数字的左侧)

5200 - 0025 = 5175
7551 - 1557 = 5994
9954 - 4599 = 5355
5553 - 3555 = 1998
9981 - 1899 = 8082
8820 - 0288 = 8532
8532 - 2358 = 6174

现在目的是验证这个定理&找到迭代次数达到6174。

  

任何人都可以提供更好的算法吗?这是我的代码。

public int VerifyKaprekarTheorem(int m) {
    if (m <= 1000 || m > 9999) {
        return -1;
    }
    String orginal = String.valueOf(m);
    int count = 0;
    while (true) {
        int Max = Integer.parseInt(sortString(orginal, false));
        int Min = Integer.parseInt(sortString(orginal, true));
        count++;
        int diff = Max - Min;
        if (diff == 6174) {
            break;
        }
        orginal = String.valueOf(diff);
    }
    return count;
}

public static String sortString(String Source, boolean assendingOrder) {
    char[] original = String.valueOf(Source).toCharArray();
    Arrays.sort(original);
    if (assendingOrder) {
        return new String(original);
    }
    char[] dessending = new char[original.length];
    for (int i = original.length - 1; i >= 0; i--) {
        dessending[i] = original[(original.length - 1) - i];
    }
    return new String(dessending);
}
  

和testcase

public void testCase01() {
    int actual = VerifyKaprekarTheorem(4321);   
    assertEquals(3, actual);
}

1 个答案:

答案 0 :(得分:0)

我已将Integer更改为String,然后将char数组更改为再次排序整数转换。

public int VerifyKaprekarTheorem(int m) {
    if (m <= 1000 || m > 9999) {
        return -1;
    }
    int count = 0;
    while (true) {
        int Max = largestNumber(m);
        int Min = smallestNumber(m);
        count++;
        m = Max - Min;
        if (m == 6174) {
            break;
        }
    }
    return count;
}
private static int largestNumber(int input) {
    int[] numbers = new int[10];
    for (int i = input; i != 0; i /= 10) {
        numbers[i % 10]++;
    }
    int counter = 0;
    int result = 0;
    for (int i = 0; i < 10; counter += numbers[i++]) {
        result += (int) ((Math.pow(10, numbers[i]) * i - 1) / 9) * Math.pow(10, counter);
    }
    return result;
}

private static int smallestNumber(int input) {
    int[] numbers = new int[10];
    for (int i = input; i != 0; i /= 10) {
        numbers[i % 10]++;
    }
    int counter = 0;
    int result = 0;
    for (int i = 9; i >= 0; counter += numbers[i--]) {
        result += (int) ((Math.pow(10, numbers[i]) * i - 1) / 9) * Math.pow(10, counter);
    }
    return result;
}