问题描述
对于任意一个4位数n,进行如下的运算:
1.将组成该4位数的4个数字由大到小排列,形成由这4个数字构成的最大的4位数。
2.将组成该4位数的4个数字由小到大排列,形成由这4个数字构成的最小的4位数(如果4个数中含有0,则得到的数不足4位)。
3.求这两个数的差,得到一个新的4位数(高位0保留),这称为对n进行了一次卡布列克运算。存在这样一个规律:对一个各位数字不全相同的4位数重复进行若干次卡布列克运算,最后得到的结果总是6174,这种数被称为卡布列克数,请用python编程证明此规律。
这个问题的本质就是:现有一个4位数number,求出number中4个数字构成的最大的4位数max_number和number中4个数字构成的最小的4位数min_number。使用max_number减去min_number得到sub_number,查看sub_number是否等于6174。如果sub_number不等于6174,则把sub_number当成number来重复上面的过程,直到sub_number等于6174。为了防止出现sub_number等于0而变成死循环的情况,在sub_number等于0时也需要结束运算。
求4个数字构成的最大4位数
我们可以把这个4位数转换为一个字符串,每次从字符串中找出最大的数字放到一个新字符串中,再去除字符串中最大的数字。如此循环4次即可得到最大4位数的新字符串,再把这个新字符串转换为整型,就得到了最大4位数。代码如下:
def max_number(number: int):
"""
生成number中的4个数字组成的最大4位数
:param number: 一个整数
:return: 最大4为数
"""
s_number = str(number).zfill(4) # 把整数转换为字符串,用zfill处理一下字符串,当number不足4位时,在前面添0补齐
r_number = '' # 定义一个新字符串
for i in range(4): # 循环4次
r_number += max(s_number) # 使用max找出字符串中最大的数字,放到新字符串中
s_number = s_number.replace(max(s_number), '', 1) # 把字符串中最大的数字替换为空字符,防止有重复数字,只替换一个
return int(r_number) # 返回最大4为数
求4个数字构成的最小4位数
我们可以把这个4位数转换为一个字符串,每次从字符串中找出最小的数字放到一个新字符串中,再去除字符串中最小的数字。如此循环4次即可得到最小4位数的新字符串,再把这个新字符串转换为整型,就得到了最小4位数。代码如下:
def min_number(number: int):
"""
生成number中的4个数字组成的最小4位数
:param number: 一个整数
:return: 最小4为数
"""
s_number = str(number).zfill(4) # 把整数转换为字符串,用zfill处理一下字符串,当number不足4位时,在前面添0补齐
r_number = '' # 定义一个新字符串
for i in range(4): # 循环4次
r_number += min(s_number) # 使用min找出字符串中最小的数字,放到新字符串中
s_number = s_number.replace(min(s_number), '', 1) # 把字符串中最小的数字替换为空字符,防止有重复数字,只替换一个
return int(r_number) # 返回最小4为数
做卡布列克运算
现有一个4位数number各位数字不全相同,在一个循环中,使用max_number函数求出number的最大4位数b_number,使用min_number函数求出number的最小4位数l_number。判断b_number减去l_number的结果是否等于6174或0,如果不等于6174或0,把结果赋值给number重复上面的步骤(循环),如果等于6174或0结束循环。代码如下:
def cableck_constant(number: int):
"""
卡布列克常数
:param number: 一个4位正整数
:return:
"""
if type(number) != int: # 检查number的类型是不是整型
raise TypeError('number is not int') # 不是则整型抛出类型错误
if number < 1000 or number > 9999: # 检查number的值是不是4位数
raise ValueError('number range [1000, 9999]') # 不是则抛出值错误
while number != 6174 and number != 0: # 当number等于6174或0时结束循环
l_number = min_number(number) # 求出最小4位数
b_number = max_number(number) # 求出最大4位数
number = b_number - l_number # 把最大4位数和最小4位数的差赋值给number
print(f'{b_number} - {l_number:4} = {number}') # 打印一下计算过程
完整代码
把上面3个函数合起来就能得到完整代码:
def min_number(number: int):
"""
生成number中的4个数字组成的最小4位数
:param number: 一个整数
:return: 最小4为数
"""
s_number = str(number).zfill(4) # 把整数转换为字符串,用zfill处理一下字符串,当number不足4位时,在前面添0补齐
r_number = '' # 定义一个新字符串
for i in range(4): # 循环4次
r_number += min(s_number) # 使用min找出字符串中最小的数字,放到新字符串中
s_number = s_number.replace(min(s_number), '', 1) # 把字符串中最小的数字替换为空字符,防止有重复数字,只替换一个
return int(r_number) # 返回最小4为数
def max_number(number: int):
"""
生成number中的4个数字组成的最大4位数
:param number: 一个整数
:return: 最大4为数
"""
s_number = str(number).zfill(4) # 把整数转换为字符串,用zfill处理一下字符串,当number不足4位时,在前面添0补齐
r_number = '' # 定义一个新字符串
for i in range(4): # 循环4次
r_number += max(s_number) # 使用max找出字符串中最大的数字,放到新字符串中
s_number = s_number.replace(max(s_number), '', 1) # 把字符串中最大的数字替换为空字符,防止有重复数字,只替换一个
return int(r_number) # 返回最大4为数
def cableck_constant(number: int):
"""
卡布列克常数
:param number: 一个4位正整数
:return:
"""
if type(number) != int: # 检查number的类型是不是整型
raise TypeError('number is not int') # 不是则整型抛出类型错误
if number < 1000 or number > 9999: # 检查number的值是不是4位数
raise ValueError('number range [1000, 9999]') # 不是则抛出值错误
while number != 6174 and number != 0: # 当number等于6174或0时结束循环
l_number = min_number(number) # 求出最小4位数
b_number = max_number(number) # 求出最大4位数
number = b_number - l_number # 把最大4位数和最小4位数的差赋值给number
print(f'{b_number} - {l_number:4} = {number}') # 打印一下计算过程
cableck_constant(1234)
执行结果如下: