PAT Basic 1019 数字黑洞

给定任一个各位数字不完全相同的 4 位正整数,如果我们先把 4 个数字按非递增排序,再按非递减排序,然后用第 1 个数字减第 2 个数字,将得到一个新的数字。一直重复这样做,我们很快会停在有“数字黑洞”之称的6174,这个神奇的数字也叫 Kaprekar 常数。

例如,我们从6767开始,将得到

7766 - 6677 = 1089
9810 - 0189 = 9621
9621 - 1269 = 8352
8532 - 2358 = 6174
7641 - 1467 = 6174
... ...

现给定任意 4 位正整数,请编写程序演示到达黑洞的过程。

输入格式:
输入给出一个 (0,104) 区间内的正整数N

输出格式:
如果N的 4 位数字全相等,则在一行内输出N - N = 0000;否则将计算的每一步在一行内输出,直到6174作为差出现,输出格式见样例。注意每个数字按4位数格式输出。

输入样例 1:

6767

输出样例 1:

7766 - 6677 = 1089
9810 - 0189 = 9621
9621 - 1269 = 8352
8532 - 2358 = 6174

输入样例 2:

2222

输出样例 2:

2222 - 2222 = 0000

 

思路:

  1. pow(10, i)分解整数的每一位,正序,逆序输出;
  2. 输出的时候要用0补足4位;
printf("%04d\n", N);

 

代码

#include
#include

int main()
{
    int N = 0, RN = 0, RES = 1, temp = 0;
    int ar[4];

    scanf("%d", &N);

    while(RES != 6174 && RES != 0)
    {
        // 将4位数分别写入数组
        for(int i = 0; i < 4; i++)
        {
            ar[i] = N / pow(10, 3-i);
            N %= (int) pow(10, 3-i);
        }

        // 数组排序
        for(int i = 0; i < 3; i++)
        {
            for(int j = 0; j < 3 - i; j++)
            {
                if(ar[j] < ar[j + 1])
                {
                    temp = ar[j];
                    ar[j] = ar[j + 1];
                    ar[j + 1] = temp;
                }       
            }
        }

        // 正序,逆序输出
        N = RN = 0;
        for(int i = 0; i < 4; i++)
        {
            N   += ar[i]*pow(10, 3-i);
            RN  += ar[i]*pow(10, i);
        }
        RES = N - RN;
        printf("%04d - %04d = %04d\n", N, RN, RES);

        // 将RES设置为下一个循环的N
        N = RES;
    }

    return 0;
}

 

疑问未解决

本来想将4 个数字按非递增排序,再按非递减排序,这个功能写成一个函数void maxmin(int *N, int *RN),发现多次调用以后,地址里面的值会逐渐变成0

写了一个简单的检验程序:

#include

void swap(int *N, int *M)
{
    int temp;
    *N = temp;
    *N = *M;
    *M = temp;
}

int main()
{
    int N = 1, M = 2, count = 3;
    printf("%d: %p %d: %p\n", N, &N, M, &M);

    while(count--)
    {
        swap(&N, &M);
        printf("%d: %p %d: %p\n", N, &N, M, &M);
    }

    return 0;
}

输出:

1: 0x7ffeee10abc8 2: 0x7ffeee10abc4
2: 0x7ffeee10abc8 0: 0x7ffeee10abc4
0: 0x7ffeee10abc8 0: 0x7ffeee10abc4
0: 0x7ffeee10abc8 0: 0x7ffeee10abc4

至今不知为何。
现在知道了,这个代码写错了

void swap(int *N, int *M)
{
    int temp;
    temp = *N;
    *N = *M;
    *M = temp;
}

 

心得

数据量比较少的,可以用qsort()进行排序。

代码示例:

#include
#include

int cmp(const void *a, const void *b) {return *(int *)a - *(int *)b;}

int main()
{
    int ar[4] = {4,2,1,3};
    qsort(ar, 4, sizeof(int), cmp);
    for(int i = 0; i < 4; i++)
        printf("ar[%d] = %d\n", i, ar[i]);

    return 0;
}

注意cmp函数的写法

// 大排到小
int cmp(const void *a, const void *b) {return *(int *)b - *(int *)a;}

// 小排到大
int cmp(const void *a, const void *b) {return *(int *)a - *(int *)b;}

 
贴一个用qsort()排序的解法(来自OliverLew),有兴趣的可以了解一下。

#include 
#include 

int cmp(const void *a, const void *b) {return *(int*)b - *(int*)a;}

int sort(int n)
{
    int digits[4] = {n/1000, n%1000/100, n%100/10, n%10};
    qsort(digits, 4, sizeof(int), cmp);
    return digits[0] * 1000 + digits[1] * 100 + digits[2] * 10 + digits[3];
}

int reverse(int n)
{
    return n/1000 + n%1000/100 * 10 + n%100/10 * 100 + n%10 * 1000;
}

int main()
{
    int N;
    scanf("%d", &N);
    while(1)
    {
        N = sort(N);
        printf("%04d - %04d = %04d\n", N, reverse(N), N - reverse(N));
        N = N - reverse(N);
        
        if(N == 0 || N == 6174) 
            break;
    }
    return 0;
}

你可能感兴趣的:(PAT Basic 1019 数字黑洞)