[导读]:超平老师的Scratch蓝桥杯真题解读系列在推出之后,受到了广大老师和家长的好评,非常感谢各位的认可和厚爱。作为回馈,超平老师计划推出《Python蓝桥杯真题解析100讲》,这是解读系列的第33讲。
读数系统,本题是2020年10月30日举办的第11届蓝桥杯青少组Python编程国赛真题,题目要求设计一个读数系统,将输入的数字按照中文读写的规范转为汉语拼音字串。
先来看看题目的要求吧。
一.题目说明
提示信息:
假设给出一个数值9876543201,直接看这个数字很难直观准确的读出来,为了准确快速的读出一个数字,想请你编写一个读数系统。
中文读数规则:
1). 从高位读起,先读亿级,再读万级,最后读个级;
2). 读亿级和万级时按读个级的方法来读,读完亿级后加上一个“亿”字,读完万级后加上一个“万”字;
3). 每级末尾不管有几个0都不读,每级中间和前面有一个或连续几个0,都只读一个0。
编程实现:
输入一个小于一百亿的正整数n(1 ≤ n < 10000000000),按照中文读写的规范转为汉语拼音字串,相邻的两个音节用一个空格符隔开。
例如:给定一个阿拉伯数字串“9876543201”
中文读写的规范:九十八亿七千六百五十四万三千二百零一
汉语拼音字串:jiu shi ba yi qi qian liu bai wu shi si wan san qian er bai ling yi
输入描述:
输入一个小于一百亿的正整数n(1≤n<10000000000)
输出描述:
输出其对应汉语拼音字串,相邻的两个音节用一个空格符隔开
样例输入:
54321001
样例输出:
wu qian si bai san shi er wan yi qian ling yi
二.思路分析
这是一道模拟算法题,考查的知识点主要包括字符串、列表和函数。
根据题目的要求,数字的范围为1~10000000000,很显然数字规模比较大,不适合挨个处理。
还记得我们的计算思维吗,就是如何将复杂问题拆分成简单问题。
仔细分析一下,你会发现个级、万级和亿级的读法是一样的,比如:
123412341234
一千二百三十四亿一千二百三十四万一千二百三十四
除了单位不同,其数字部分的读法完全一致,因此我们只需要先处理好4位数字的读法,再进行连接就可以了,但是这里有一个特殊情况,就是数字零,需要重点分析和处理。
因此,我们可以将问题拆分为如下3个步骤:
-
实现4位数字的读法;
-
将输入数字分为3段处理;
-
考虑并完善特殊情况;
4位数的读法是解决问题的第一步,也是最重要的一步,由于Python不能自动将数字转成汉语拼音,所以要先定义好每个数字和单位的拼音。
我们可以使用列表来保存这些拼音,数字的拼音列表可以定义如下:
# 定义数字的拼音
number = ["ling","yi","er","san","si","wu","liu","qi","ba","jiu"]
单位的拼音列表可以定义如下:
# 定义单位的拼音
unit = ["qian","bai","shi",""]
注意,个位是不需要读出来的,所以将其定义为空,保留这一位是方便理解和计算。
然后使用循环4位数字串进行遍历,将每个数字的拼音和单位进行连接,比如数字为:
8765
先获取第一个数字8,通过下标获取number列表中的拼音number[8] = "ba",同时通过unit列表找到其对应的单位"qian",将二者连接起来,就是"ba qian"。
再依次处理数字7、6、5,最后可以得到完整的拼音”ba qian qi bai liu shi wu“。
当然,这是理想状态,还需要考虑两种特殊情况:
-
位数不足4位;
-
数字包含0;
位数不足4位时,在循环处理时,数字的拼音是正常的,但是单位不能一一对应,需要额外处理一下,比如只有3位数字时,最高是百,因此需要数字的长度来计算其下标。
数字包含0时,问题就变得复杂了一些,包括两种情况:
1). 末尾数字是0时,0是不读的;
2). 有连续的0时,只需要读1次;
为了方便,我们可以将这个处理过程定义成函数,然后再将输入的数字拆分成3段,也就是亿级、万级和个级,分别调用函数获取其拼音字符串,再考虑一些特殊情况,就可以得到完整的汉语拼音串了。
思路有了,接下来,我们就进入具体的编程实现环节。
三.编程实现
根据上面的思路分析,我们分4步来编写程序:
-
定义列表
-
定义函数读取4位数
-
分段处理
-
完善程序
1. 定义列表
这一步比较简单,定义两个列表,分别是数字拼音和单位拼音,代码如下:
2. 定义函数读取4位数
根据前面的思路分析,我们定义函数如下:
代码不少,说明6点:
1). 读取数字时,是以字符串的方式来处理的,所以代码都是围绕着字符串处理进行的;
2). 在获取数字拼音时,需要先获取字符对应的数字即s[i],再将s[i]作为下标获取拼音,不过要使用int()函数将其转成整型;
3). 在获取单位的时候,下标不仅和i有关系,和字符串的长度l也有关系;
4). 对于连续数字0的处理,这里使用了一个变量"flag",如果当前数数字为0,就将flag设为1,否则设置为0,再根据这个flag来决定是否需要连接”ling“和单位拼音;
5).对于末尾数字0的处理,如果末尾为0,则删除字符串末尾的"ling",当然如果数字本身为0,则不用删除;
6). 由于在连接时,会在每个拼音后面增加一个空格,所以在得到完整的字符串后,使用rstrip()函数删除末尾的空格,这可以避免两个拼音之间出现两个空格的情况。
完成这一步,建议先测试一下,确保代码和逻辑的正确性,再继续下一步。
3. 分段处理
有了read_number()函数,接下来就方便了,将输入的数字拆分成3段来处理:
3.1 亿级
输入的数字范围是1~10000000000,因此需要对数字进行判断,如果长度是8位,才需要处理,对应的代码如下:
代码比较好理解,简单说明4点:
1). 变量"res"用来表示最后的结果,也就是完整的拼音串,初始值设为空;
2). 如果字符串长度大于8,就截取亿级部分的数字串,这里使用了s[:-8]的编程技巧;
3). 获取亿级的拼音串后,在尾部增加单位"yi",注意左右各有一个空格;
4). 亿级处理完成,就删除亿级的数字串,并保存到变量"s"中。
3.2 万级
对于万级的处理和亿级基本类似,继续编写代码如下:
由于万级的数字处在亿级和个级之间,有可能出现全0的情况,比如1200003456,这种情况下,万是不需要读的。
因此,这里做了一个判断,如果万级的4位不是全0,则需要读数,然后在末尾加上"wan",最后去掉万级,只保留各级的数字串。
3.3 个级
个级的情况比较简单,直接读取即可,继续编写代码如下:
处理完亿级,万级和个级,去掉最后的空格,基本上就可以了。
4. 完善细节
到这里,基本上就可以处理大部分数据了,但是还有一个特殊的情况,就是万级数据全为0,个级有千位,比如1200003456,使用上面的程序,结果如下:
很显然,这里少了一个"ling",所以,针对这种情况,需要单独处理,修改亿级代码如下:
再次测试,效果如下:
这一次,就没有问题了,注意,我们需要多测试一些数据,尤其是包含0的情况,下面这些是建议测试的数据:
1
10
100
1000
10000
100000
1000000
10000000
100000000
100000000
1000000000
12
123
1234
12345
123456
1234567
12345678
123456789
1234567891
12345678912
102
120
1023
1203
1230
1002
1020
1200
10002
10020
10200
12000
100002
100020
100200
102000
120000
1000002
1000020
1000200
1002000
1020000
1200000
......
至此,整个程序就全部完成了,你也可以输入不同的数字来测试效果。
四.总结与思考
本题代码在35行左右,涉及到的知识点包括:
-
循环语句,主要for...in循环;
-
条件语句,包括单分支和双分支;
-
字符串处理;
-
列表的使用;
-
函数的定义及使用;
作为国赛真题,本题难度较大,除了常见的Pytho基础知识外,更重要的是逻辑思维能力和解决问题的方法和能力。
对于任何一个复杂问题,我们都可以尝试运用计算思维对其进行拆分,将其拆分成若干简单问题,将简单问题一一解决了,复杂问题也就八九不离十了。
同时,要注意细节的把握和处理,对所有的情况都要做到不重复不遗漏。
超平老师给你留一道思考题,对于本题的测试数据,有没有好的办法,做到快速测试呢?
你还有什么好的想法和创意吗,也非常欢迎和超平老师分享探讨。
如果你觉得文章对你有帮助,别忘了点赞和转发,予人玫瑰,手有余香😄
需要源码的,可以移步至“超平的编程课”gzh。