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