C語言驗(yàn)證6174數(shù)學(xué)問題
有意思的數(shù)學(xué)問題
任意4位不完全一樣的數(shù)字,能組合出的最大數(shù)字減去能組合出的最小數(shù)字,得到一個(gè)新的數(shù)字(3位數(shù)補(bǔ)0),重復(fù)以上操作,不超過7個(gè)循環(huán),必然得到一個(gè)數(shù):6174
這個(gè)問題是之前發(fā)布的文章,有讀者朋友在文章留言提到這個(gè),我覺得比較有意思,就拿出來分享,最近迷上這類有意思的東西,而且是熱乎原創(chuàng)的。
輸入一個(gè)數(shù)3256,將他從小到大輸出,就是2356
1、我寫的代碼
剛開始寫的第一份代碼,有個(gè)缺陷,寫完后看到另一個(gè)讀者提交的答案,已經(jīng)考慮到了這個(gè)問題,自我感覺,大神還是挺多的。
我說下我代碼里面的幾個(gè)重點(diǎn)
1、我使用get來獲取輸入的字符,所以呢,再使用arr[i] - 0x30把a(bǔ)scii碼轉(zhuǎn)換成數(shù)字,比如字符 1轉(zhuǎn)換成數(shù)字1,就需要把字符1對應(yīng)的值0x31減去0x30得到數(shù)字1。
2、關(guān)于冒泡排序,冒泡排序網(wǎng)上有很多講解,第一個(gè)for循環(huán)是從0開始到len-1結(jié)束的,關(guān)鍵在于第二個(gè)for循環(huán),第二個(gè)for循環(huán)從第一個(gè)for循環(huán)的值的下一個(gè)位置開始到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個(gè)不同的數(shù)字*/
?while(j(nums,4)?==?false)
?{
??printf("input:");
??gets(nums);
?}
?
????/*7個(gè)循環(huán)進(jì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
基于嚴(yán)謹(jǐn)性,我寫了個(gè)測試程序來檢驗(yàn)我的這段代碼,我總是覺得這樣的理論不可思議,用一個(gè)數(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)生一個(gè)各位數(shù)不相等的四位隨機(jī)數(shù)
*入口參數(shù):random為返回的隨機(jī)數(shù)
*返?回?值:無
*備?注:先生成一個(gè)0-9的整數(shù)數(shù)組,再隨機(jī)從中取四個(gè)數(shù),每取一個(gè)將該位置為-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個(gè)隨機(jī)數(shù)
????????k?=?(int)rand()?%?10;//k為下標(biāo)
????????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個(gè)不同的數(shù)據(jù),來測試是不是結(jié)果都是6174,結(jié)果確實(shí)是這樣。
代碼輸出,因?yàn)檩敵霰容^多,我只截取了最后的一些
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、有個(gè)讀友提供的代碼
基本思路都差不多,而且里面用到的排序思路都是一樣的。
#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;
}
代碼運(yùn)行輸出
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









