给定任一个各位数字不完全相同的 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
思路:
- 用
pow(10, i)
分解整数的每一位,正序,逆序输出; - 输出的时候要用
0
补足4
位;
printf("%04d\n", N);
代码
#include<stdio.h>
#include<math.h>
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<stdio.h>
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<stdio.h>
#include<stdlib.h>
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 <stdio.h>
#include <stdlib.h>
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;
}