Given an integer with no more than 9 digits, you are supposed to read it in the traditional Chinese way. Output Fu
first if it is negative. For example, -123456789 is read as Fu yi Yi er Qian san Bai si Shi wu Wan liu Qian qi Bai ba Shi jiu
. Note: zero (ling
) must be handled correctly according to the Chinese tradition. For example, 100800 is yi Shi Wan ling ba Bai
.
Each input file contains one test case, which gives an integer with no more than 9 digits.
For each test case, print in a line the Chinese way of reading the number. The characters are separated by a space and there must be no extra space at the end of the line.
-123456789
Fu yi Yi er Qian san Bai si Shi wu Wan liu Qian qi Bai ba Shi jiu
100800
yi Shi Wan ling ba Bai
本题 25 分,这道题是非常复杂,因为提供的样例很少,规则也需要自己根据生活经验去分析,最后还要考虑些边界条件。对问题模拟的好坏直接影响代码编写的复杂程度,因此需要静心分析,能发现规律的利用迭代、循环,没有规律的,枚举出各种条件、情况,梳理清晰。
本文用Python实现,但是基本思路和其它语言差别不大。另外,这道题也可以用正则表达式处理,但是输入的值最多是9位,而且问题简化后完全可以枚举出几种情况,所以不建议用正则表达式。
首先,每一位的数字对应一个汉字,0~9一共10个数字用digit[]
表示;从低位数起,每个4位都是以“(个)、十、百、千”为后缀在数字之后,用place[]
表示;每个4位在读完后还要加个后缀,如“万”、“亿”,用suffix[]
表示。因此,我们可以将整个数字按4位切分成若干段,每一段译出数字、“十百千”,封装成一个函数。调用一次后根据这是第i
个段对应加上“万”、“亿”的后缀。最终合并起来,如果是负数再在头部加Fu
即可。
其次,最为棘手的是“零”的处理,什么时候读“零”,什么时候只读一个,什么时候不读,这是这道题最难的地方。好在我们将数字按4位分割成段后问题简单多了,只用考虑最多4位的情况:
0000
,那么完全不译,函数返回空值。比如12,0000
读作十二万
、1,0000,5000
读作一亿五千
;1200
读作一千二百
、1000
读作一千
,那么末尾零的数字、在的“十百千”位也不译;2305
读作二千零五
、0234
读作零二三四
(因为这是从数字中取出四位,所以允许开头有零),那么译出“零”,但是不译“十百千”位;2003
读作二千零三
、0005
读作零五
,那么连续的零只译出一个即可,同样的,不译“十百千”位。这样就基本将问题考虑完全,那么如何实现上述对零的处理?我这里的repl()
函数是将完全不译的零替换为一个字符,如*
。repl()
函数比较取巧,首先替换完末尾零,然后考虑连续零只留一个,先将000
替换成**0
,再将00
替换成*0
,注意顺序不可以颠倒。最终返回字符串。
当solve()
函数中,按位遍历字符串时读到该位是*
就continue
跳过这一步循环,否则就按照正常的数字译出,如果数字是零,那么只译“零”不译“十百千”。遍历结束作为当前段,返回列表,
需要注意的是,输入的值可能是有前导零,如002
,所以要先处理下输入的值。还要考虑边界情况,如,输入0
(测试点3),会被上述算法当作末尾零不译,所以要在程序入口先判断下值是否为0
,如果是直接输出ling
,如果不是,再调用上述的算法。
这里提供一些额外的测试样例,以供参考
// 输入
-880808080
// 输出
Fu ba Yi ba Qian ling ba Shi Wan ba Qian ling ba Shi
// 输入
800000000
// 输出
ba Yi
// 输入
80000008
// 输出
ba Qian Wan ling ba
// 输入
0
// 输出
ling
// 输入
002
// 输出
er
// 输入
1010010
// 输出
yi Bai ling yi Wan ling yi Shi
// 输入
1000010
// 输出
yi Bai Wan ling yi Shi
// 输入
100000000
// 输出
yi Yi
from math import ceil
def repl(s):
sp = s.rstrip('0')
s = sp + '*' * (len(s)-len(sp))
s = s.replace('000', '**0').replace('00', '*0')
return s
def solve(part):
if part == '0000':
return []
part = repl(part)
words = []
for i, dig in enumerate(part[::-1]):
if dig == '*':
continue
dig = int(dig)
if dig:
words.append( (digit[dig] + ' ' + place[i]).strip() )
else:
words.append( digit[dig] )
return words
digit = ['ling', 'yi', 'er', 'san', 'si', 'wu', 'liu', 'qi', 'ba', 'jiu']
place = ['', 'Shi', 'Bai', 'Qian']
suffix = ['', 'Wan', 'Yi']
result = []
number = str(int(input()))
if number.startswith('-'):
negative = True
number = number.lstrip('-')
else:
negative = False
if number != '0':
for i in range( ceil(len(number)/4) ):
part = number[-(1+i*4):-(5+i*4):-1][::-1]
part = solve(part)
if part:
result.append(suffix[i])
result.extend(part)
if negative:
result.append('Fu')
print(' '.join(result[::-1]).strip())
else:
print(digit[0])
使用正则表达式处理这道题的“零”问题更容易,而且还可以得到连续零的起讫下标,将字符串转换为列表就可以依据得到的下标直接替换。
[0]{1,}$
import re
part = '1034000'
part = re.sub(r'[0]{1,}$', '*', part)
>> '1034***'
(0){2,}
import re
part = '1034007009'
find = re.finditer(r'(0){2,}', part)
for f in find:
print(f.span())
>> (4, 6)
>> (7, 9)
https://www.liuchuo.net/archives/2204
https://zhuanlan.zhihu.com/p/346321610