PAT09:数字黑洞

9.数字黑洞

题目

题目描述

1
2
3
4
5
6
7
8
9
10
11
12
13
给定任一个各位数字不完全相同的4位正整数,如果我们先把4个数字按非递增排序,再按非递减排序,然后用第1个数字减第2个数字,将得到
一个新的数字。一直重复这样做,我们很快会停在有“数字黑洞”之称的6174,这个神奇的数字也叫Kaprekar常数。

例如,我们从6767开始,将得到

7766 - 6677 = 1089
9810 - 0189 = 9621
9621 - 1269 = 8352
8532 - 2358 = 6174
7641 - 1467 = 6174
... ...

现给定任意4位正整数,请编写程序演示到达黑洞的过程。

输入描述:

1
输入给出一个[1000, 10000)区间内的正整数N

输出描述:

1
2
如果N4位数字全相等,则在一行内输出“N - N = 0000”;否则将计算的每一步在一行内输出,直到6174作为差出现,输出格式见样例,每行中间没有空行。注意每个数字按4位数格
式输出。

输入例子:

1
6767

输出例子:

1
2
3
4
7766 - 6677 = 1089
9810 - 0189 = 9621
9621 - 1269 = 8352
8532 - 2358 = 6174

题解

  • 输入与处理

    首先,要考虑输入的读取,使用input方法读取的是字符串类型。如果不满4位,需要使用字符串的zfill方法进行补齐。

  • 字符串排序

    使用sort方法对4位字符串进行排序,默认是非递减。使用参数reverse=True,得到非递增。

  • 差值计算

    将排序后的字符串使用int转换为整数,相减得到结果。

  • 格式化输出

    根据题目的格式进行输出,再利用递归,将输出作为下一步的输入再判断。

  • 边界条件

    如果输入字符串的4位数字均相等,则做特殊输出:’N - N = 0000’。

    如果输入为目标字符串6147,则终止递归。(特殊情况,如果第一次输入是6147需计算一次)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
def func(num,count):
num = num.zfill(4)
if int(num) == 6174:
if count != 0:
return 0
if num[0]==num[1]==num[2]==num[3]:
print(num+' - '+num+' = 0000 ')
return 0
max_com = ''.join(sorted(num,reverse=True))
min_com = ''.join(sorted(num))
resTmp = int(max_com) - int(min_com)
print(max_com+' - '+min_com+' = '+str(resTmp))
count += 1
return func(str(resTmp),count)

num = input()
count = 0
func(num,count)
# func('6214')

知识点

输入的读取

1、input()方法:读取一行输入,返回的是字符串类型,去掉了换行符。

2、sys.stdin文件对象(不会自动转换类型、包含换行符):

  • read()方法:读取所有输入
  • readline()方法:读取一行输入

字符串补齐

1、zfill()方法(使用0填充):

1
2
3
s = "42"
s = s.zfill(4)
print(s) # 0042

2、 rjust()方法(可指定字符填充):

1
2
3
s = "42"
s = s.rjust(4, "2")
print(s)

3、使用 f-string方法:

1
2
3
s = "42"
s = f"{int(s):04d}" # 04d 表示至少 4 位,不足的地方用零填充
print(s)

可以填充的为0和空格。04中的0表示填充字符,4表示填充到哪个宽度。

还可以选择填充后的对齐:

1
2
3
f"{5:<4d}"  # 左对齐
f"{5:>4d}" # 右对齐
f"{5:^4d}" # 居中对齐

常见的类型转换符:

  • **d**:整数(decimal)
  • **f**:浮动小数点数
  • **s**:字符串
  • **x**:十六进制整数(小写)
  • **X**:十六进制整数(大写)
  • **e**:科学计数法表示的浮动小数