C語言驗證6174數(shù)學(xué)問題
有意思的數(shù)學(xué)問題
任意4位不完全一樣的數(shù)字,能組合出的最大數(shù)字減去能組合出的最小數(shù)字,得到一個新的數(shù)字(3位數(shù)補0),重復(fù)以上操作,不超過7個循環(huán),必然得到一個數(shù):6174
這個問題是之前發(fā)布的文章,有讀者朋友在文章留言提到這個,我覺得比較有意思,就拿出來分享,最近迷上這類有意思的東西,而且是熱乎原創(chuàng)的。
輸入一個數(shù)3256,將他從小到大輸出,就是2356
1、我寫的代碼
剛開始寫的第一份代碼,有個缺陷,寫完后看到另一個讀者提交的答案,已經(jīng)考慮到了這個問題,自我感覺,大神還是挺多的。
我說下我代碼里面的幾個重點
1、我使用get來獲取輸入的字符,所以呢,再使用arr[i] - 0x30把ascii碼轉(zhuǎn)換成數(shù)字,比如字符 1轉(zhuǎn)換成數(shù)字1,就需要把字符1對應(yīng)的值0x31減去0x30得到數(shù)字1。
2、關(guān)于冒泡排序,冒泡排序網(wǎng)上有很多講解,第一個for循環(huán)是從0開始到len-1結(jié)束的,關(guān)鍵在于第二個for循環(huán),第二個for循環(huán)從第一個for循環(huán)的值的下一個位置開始到len結(jié)束。
關(guān)于冒泡排序的思路,我做了一組圖示,如附圖1
#include?"stdio.h"
#include?"stdbool.h"
/*判斷數(shù)組里面是否有一樣的數(shù)*/
int?j(char?*arr,int?len)
{
?int?i,j;
?for(i=0;i??arr[i]?=?arr[i]?-?0x30;/*字符轉(zhuǎn)成數(shù)字*/
?for(i=0;i-1;i++)
??for(j=i+1;j???if(arr[i]?==?arr[j])
????return?false;
?return?true;
}
/*判斷是否不足夠4位數(shù)字*/
int?j2(int?diff)
{
?if(diff<10){
??diff=diff*1000;
?}else?if(diff<100){
??diff?=?diff*100;
?}else?if(diff<1000){
??diff=diff*10;
?}
}
/*升序*/
int?m(char?*arr,int?len)?
{
?int?i,j;
?for(i=0;i-1;i++)
??for(j=i+1;j/*和之后的位置比較*/
???if(?arr[i]?????arr[i]?^=?arr[j];
????arr[j]?^=?arr[i];
????arr[i]?^=?arr[j];
???}?
}
/*降序*/
int?n(char?*arr,int?len)?
{
?int?i,j;
?for(i=0;i-1;i++)
??for(j=i+1;j???if(?arr[i]?>?arr[j]){
????arr[i]?^=?arr[j];
????arr[j]?^=?arr[i];
????arr[i]?^=?arr[j];
???}
?//printf("%d%d%d%d\n",arr[0],arr[1],arr[2],arr[3]);?
}
int?main(void)
{
?int?dmax,dmin,diff,i;
?char?nums[4];
?char?max[4];
?char?min[4];?
?
?/*輸入4個不同的數(shù)字*/
?while(j(nums,4)?==?false)
?{
??printf("input:");
??gets(nums);
?}
?
????/*7個循環(huán)進行判斷*/
?for(i=0;i<7;i++)
?{
?????????/*排序*/
??m(nums,4);
??//printf("%d%d%d%d\n",nums[0],nums[1],nums[2],nums[3]);
??dmax?=?nums[0]*1000?+?nums[1]*100+nums[2]*10+nums[3];
??/*排序*/
?????????n(nums,4);
??//printf("%d%d%d%d\n",nums[0],nums[1],nums[2],nums[3]);
??dmin?=?nums[0]*1000?+?nums[1]*100+nums[2]*10+nums[3];
??diff?=?dmax?-?dmin;
??diff?=?j2(diff);
??printf("dmax:%d?dmin:%d?diff:%d\n",dmax,dmin,diff);
??if(diff?==?6174){
???printf("find?6174\n");
???break;
??}
??nums[0]?=?diff/1000;
??nums[1]?=?diff%1000/100;
??nums[2]?=?diff%1000%100/10;
??nums[3]?=?diff%10;
?}
?
?getchar();
?return?(0);?
}?
代碼輸出
input:1234
dmax:4321?dmin:1234?diff:3087
dmax:8730?dmin:378?diff:8352
dmax:8532?dmin:2358?diff:6174
find?6174
基于嚴謹性,我寫了個測試程序來檢驗我的這段代碼,我總是覺得這樣的理論不可思議,用一個數(shù)字是不可能代表所有的可能性的,所以有了下面的這段代碼。
#include?"stdio.h"
#include?"stdbool.h"
#include?"time.h"
/*判斷數(shù)組里面是否有一樣的數(shù)*/
int?j(char?*arr,int?len)
{
?int?i,j;
?for(i=0;i??arr[i]?=?arr[i]?-?0x30;/*字符轉(zhuǎn)成數(shù)字*/
?for(i=0;i-1;i++)
??for(j=i+1;j???if(arr[i]?==?arr[j])
????return?false;
?return?true;
}
/*判斷是否不足夠4位數(shù)字*/
int?j2(int?diff)
{
?if(diff<10){
??diff=diff*1000;
?}else?if(diff<100){
??diff?=?diff*100;
?}else?if(diff<1000){
??diff=diff*10;
?}
}
/*升序*/
int?m(char?*arr,int?len)?
{
?int?i,j;
?for(i=0;i-1;i++)
??for(j=i+1;j/*和之后的位置比較*/
???if(?arr[i]?????arr[i]?^=?arr[j];
????arr[j]?^=?arr[i];
????arr[i]?^=?arr[j];
???}?
}
/*降序*/
int?n(char?*arr,int?len)?
{
?int?i,j;
?for(i=0;i-1;i++)
??for(j=i+1;j???if(?arr[i]?>?arr[j]){
????arr[i]?^=?arr[j];
????arr[j]?^=?arr[i];
????arr[i]?^=?arr[j];
???}
?//printf("%d%d%d%d\n",arr[0],arr[1],arr[2],arr[3]);?
}
/******************************************************************************
*函數(shù)名稱:void get_random(char * random)
*函數(shù)功能:產(chǎn)生一個各位數(shù)不相等的四位隨機數(shù)
*入口參數(shù):random為返回的隨機數(shù)
*返?回?值:無
*備?注:先生成一個0-9的整數(shù)數(shù)組,再隨機從中取四個數(shù),每取一個將該位置為-1
*******************************************************************************/
void?get_random(char?*?random)
{
????int?i,?j[10],?k;
????for?(i?=?0;?i?10;?i++){
????????j[i]?=?i;
????}
????for(i?=?0;?i?4;?i++){
????????//生成第i個隨機數(shù)
????????k?=?(int)rand()?%?10;//k為下標
????????while?(j[k]?==?-1){
????????????k?=?(k?+?1)?%?10;
????????}
????????random[i]?=?'0'?+?j[k];
????????j[k]?=?-1;
????}
}
int?main(void)
{
?int?dmax,dmin,diff,i,r,count;
?long?t;
?char?nums[4],max[4],min[4];
?
?srand((unsigned)time(&t));
?
?for(count?=?0;count?<10000;count++){
??
??get_random(nums);
??printf("%c%c%c%c\n",nums[0],nums[1],nums[2],nums[3]);
??
??for(i=0;i<7;i++){
???m(nums,4);
???dmax?=?nums[0]*1000?+?nums[1]*100+nums[2]*10+nums[3];
???n(nums,4);
???dmin?=?nums[0]*1000?+?nums[1]*100+nums[2]*10+nums[3];
???diff?=?dmax?-?dmin;
???diff?=?j2(diff);
???if(diff?==?6174){
????printf("find?6174?%d\n",count);
????break;
???}
???
???if(i?==?6?&&?diff?!=?6174)
????goto?error;
???
???nums[0]?=?diff/1000;
???nums[1]?=?diff%1000/100;
???nums[2]?=?diff%1000%100/10;
???nums[3]?=?diff%10;
??}
?}
?getchar();
?return?(0);
?error:
??printf("Can't?find?6174?%d\n",count);
?getchar();
?return?(0);?
}?
我在代碼里面測試了 10000 次數(shù)據(jù),意思就是我輸入10000個不同的數(shù)據(jù),來測試是不是結(jié)果都是6174,結(jié)果確實是這樣。
代碼輸出,因為輸出比較多,我只截取了最后的一些
find?6174?9985
9802
find?6174?9986
5908
find?6174?9987
3127
find?6174?9988
9124
find?6174?9989
5027
find?6174?9990
5304
find?6174?9991
7864
find?6174?9992
8213
find?6174?9993
4795
find?6174?9994
0184
find?6174?9995
2410
find?6174?9996
2134
find?6174?9997
5340
find?6174?9998
3294
find?6174?9999
2、有個讀友提供的代碼
基本思路都差不多,而且里面用到的排序思路都是一樣的。
#include?
int?getMax(int?byte[]){
?int?max;
?for(int?i=0;i<3;i++){
??for(int?j=i+1;j<4;j++){
???if(byte[i]????int?t=byte[i];
????byte[i]?=?byte[j];
????byte[j]?=?t;
???}
??}
?}
?//?printf("?sort?byte?is??%d??%d??%d??%d\n",byte[0],byte[1],byte[2],byte[3]);
?//?printf("<<<<<<<<<<<<<<<<<\n");?
?max?=?byte[0]*1000+byte[1]*100+byte[2]*10+byte[3];
?return?max;
}
int?getMin(int?byte[]){
?int?min;
?for(int?i=0;i<3;i++){
??for(int?j=i+1;j<4;j++){
???if(byte[i]>byte[j]){
????int?t=byte[i];
????byte[i]?=?byte[j];
????byte[j]?=?t;
???}
??}
?}
?//?printf("?sort?byte?is??%d??%d??%d??%d\n",byte[0],byte[1],byte[2],byte[3]);
?//?printf(">>>>>>>>>>>>>>>>>\n");?
?min?=?byte[0]*1000+byte[1]*100+byte[2]*10+byte[3];
?return?min;?
}
int?main(){
???int?a?=?0;
???printf("input?the?num?:\n");
?int?max;
?int?min;
?scanf("%d",&a);
?for(int?i=0;i<7;i++){
??printf("the?num:%d\n",a);
??if(a<10){
???a=a*1000;
??}
??else?if(a<100){
???a?=?a*100;
??}else?if(a<1000){
???a=a*10;
??}
??printf("deal?num:%d\n",a);
?int?byte[4]={0};
?byte[0]=a/1000;
?byte[1]=a/100%10;
?byte[2]?=?a/10%10;
?byte[3]?=?a%10;
?//?printf(">>>>>>>>>>>>>>>>>\n");?
?//?printf("byte?is??%d??%d??%d??%d\n",byte[0],byte[1],byte[2],byte[3]);
??if(a?==?6174){
???printf("bingo!!!\n");
???break;
??}
??max?=?getMax(byte);
??min?=?getMin(byte);
??printf("the?max:%d\n",max);
??printf("the?min:%d\n",min);
??a=max-min;
?}
?return?0;
}
代碼運行輸出
weiqifa@bsp-ubuntu1804:~/c$?gcc?6174.c?&&?./a.out
input?the?num?:
1234
the?num:1234
deal?num:1234
the?max:4321
the?min:1234
the?num:3087
deal?num:3087
the?max:8730
the?min:378
the?num:8352
deal?num:8352
the?max:8532
the?min:2358
the?num:6174
deal?num:6174
bingo!!!
weiqifa@bsp-ubuntu1804:~/c$
附圖1









