数字的魔法:给我任意一个四位数,通过排列和减法,最终总能得到6174——卡布列克常数。本文用代码演示了这一神奇过程,带你领略数学的奇妙和编程的乐趣。


卡布列克常数(Kablek constant):任意一个不是由完全相同数字组成的四位数,如果对它们的每位数字重新排序,组成一个较大的数和一个较小的数,然后用较大数减去较小数,差不够四位数时补零,类推下去,最后将变成一个固定的数:6174,这就是卡布列克常数。

设计思想:递归

函数设计思路

  1. 合法性判断: a) 判断是否为4位数字,不是则补高位 0 b) 判断该 4 位数是否为包含至少 2 种不同数字
  2. 将这4位数进行组合,得到 a.可组成的最大数 b.可组成的最小数 a) 组合思路: i. 建立数组 ii.对数组进行从大到小的排序 iii.将数组正序取出,则为 max。逆序取出,则为 min
  3. 用 max - min 得到 newNumber
  4. 判断 newNumber 是否为 6174 a) 若不是,则开始递归,返回步骤1 b) 若是,则表明此数是卡布列克常数。即跳出循环,记录并输入它的原始数字

代码实现

#include <stdio.h>
#include <stdbool.h>
#include <assert.h>

#define START 1000
#define END 9999

void SortArr(int* p, int sz)
{
	//合法性检查
	assert(p);

	int i = 0;
	int j = 0;
	int temp = 0;

	for (i = 0; i < sz - 1; i++)
	{
		for (j = 0; j < sz - i - 1; j++)
		{
			if (*(p + j) < *(p + j + 1))
			{
				temp = *(p + j);
				*(p + j) = *(p + j + 1);
				*(p + j + 1) = temp;
			}
		}
	}
}

bool IsKablek(int x)
{
	//合法性判断
	if (x > 9999)
	{
		return false;
	}

	int newNumber = 0;
	int temp[4] = { 0 };
	int sz = 0;

	int max = 0;
	int min = 0;

	//取所有位数
	if (x > 1000)
	{
		temp[0] = x / 1000;
	}
	if (x > 100)
	{
		temp[1] = x % 1000 / 100;
	}
	if (x > 10)
	{
		temp[2] = x % 100 / 10;
	}
	if (x > 0)
	{
		temp[3] = x % 10;
	}
	
  //所有数字相同的,不符合卡布列克常数定义,直接返回false
	if (temp[0] == temp[1] && temp[1] == temp[2] && temp[2] == temp[3])
	{
		return false;
	}

	//排序
	sz = sizeof(temp) / sizeof(int);
	SortArr(temp, sz);
	
  //将数组正序取出,赋值给为max。
  //逆序取出,赋值为min
	max = (temp[0] * 1000) + (temp[1] * 100) + (temp[2] * 10) + temp[3];
	min = (temp[3] * 1000) + (temp[2] * 100) + (temp[1] * 10) + temp[0];
	
  //得到新数字
	newNumber = max - min;

	if (newNumber == 6174)
	{
		return true;
	}
	else
	{
    //进入递归
		return IsKablek(newNumber);
	}
}

int main()
{
	int i = 0;
	int count = 0;//记录卡布列克常数在4位数中的数量
	bool flag = false;

	//遍历所有4位数
	for (i = START; i <= END; i++)
	{
		//判断是否为卡布列克常数,若是,则输出
		flag = IsKablek(i);
		if (flag)
		{
			//printf("%d ", i);
			count++;
		}
	}

	printf("\n所有4位数中,符合卡布列克常数的数,共有 %d 个\n", count);

	return 0;
}

运行结果

编码探索:卡布列克常数的算法之旅_数组

验算完毕,输出结果为8990,代表所有4位数中,除去9个所有位数字都相等的(因为这9个数字:1111,2222,...,9999,不管怎么排列,都会在第一次相减时,得到0),确实都为卡布列克常数。