Tuần 1: 2022/08/11
A.Huy (currency_to_text.py)
yêu cầu
number to text,
sửa lại hàm print_number hoặc refactor lại toàn bộ code để đúng cho mấy trường hợp: mốt, lăm, hăm... (bow)
Bug hiện tại
123455000 -> "một trăm hai mươi ba triệu bốn trăm năm mươi năm nghìn đồng"
123421000 -> "một trăm hai mươi ba triệu bốn trăm hai mươi một nghìn đồng"
source hiện tại
arr1 = {
"1": "một",
"2": "hai",
"3": "ba",
"4": "bốn",
"5": "năm",
"6": "sáu",
"7": "bảy",
"8": "tám",
"9": "chín",
}
arr2 = {
"1": "mười",
"2": "hai mươi",
"3": "ba mươi",
"4": "bốn mươi",
"5": "năm mươi",
"6": "sáu mươi",
"7": "bảy mươi",
"8": "tám mươi",
"9": "chín mươi",
}
arr3 = {
"1": "một trăm",
"2": "hai trăm",
"3": "ba trăm",
"4": "bốn trăm",
"5": "năm trăm",
"6": "sáu trăm",
"7": "bảy trăm",
"8": "tám trăm",
"9": "chín trăm",
}
def print_2(number, dv='đồng', sup='lẻ'):
ret = ""
if number < 10 and sup:
ret += sup
f = number // 10
l = number % 10
if f != 0:
ret += arr2[str(f)]
if l != 0:
ret += f" {arr1[str(l)]}"
return f"{ret} {dv}" if dv else f"{ret}"
def print_3(number, dv='nghìn'):
ret = ""
f = number // 100
l = number % 100
if f != 0:
ret += arr3[str(f)]
if l != 0:
ret += f" {print_2(l, dv=None)}"
return f"{ret} {dv}" if dv else f"{ret}"
def print_number(number):
f = number // 1000000
m = (number % 1000000) // 1000
l = (number % 1000000) % 1000
if f == 0:
raise Exception("invalid number")
if m == 0:
raise Exception("invalid number")
if f > 100:
fp = print_3(f, dv="triệu")
else:
fp = print_2(f, dv="triệu")
mp = print_3(m, dv='nghìn')
lp = print_3(l, dv='đồng')
return f"{fp} {mp} {lp}"
Giải pháp (Khoa)
Cách làm: Đọc từng số xong rồi giáp lại thành chuỗi cuối cùng
Cần update lại cho các trường hợp đặc biệt của số 1, 5 và số 0
_digits = ['', 'một', 'hai', 'ba', 'bốn', 'năm', 'sáu', 'bảy', 'tám', 'chín']
_units = ['đồng', 'mươi', 'trăm', 'ngàn', 'mươi', 'trăm', 'triệu', 'mươi', 'trăm', 'tỷ']
_special_units = {
0: {0:'', 1:'', 2:'', 3:'ngàn', 4:'', 5:'', 6:'triệu', 7:'', 8:'', 9:'tỷ', 13: 'ngàn', 14:'lẻ', 15:'', 16:'triệu', 17:'lẻ'},
1: {13: 'mốt ngàn', 16: 'mốt triệu', 4: 'mười', 7: 'mười'},
5: {13: 'lăm ngàn', 16: 'lăm triệu'},
}
class VNum:
def __init__(self, value, unit, before=None, after=None):
self.value = value
self.unit = unit
self.before = before
self.after = after
def __str__(self) -> str:
if self.unit <= 2:
return ''
if self.value == 1:
i = 10 if (self.before is not None) and (self.before > 1) else 0
s = _special_units[1].get(i + self.unit)
if s is not None: return s
if self.value == 5:
i = 10 if self.before else 0
s = _special_units[5].get(i + self.unit)
if s is not None: return s
if self.value == 0:
i = 10 if self.before and self.after else 0
s = _special_units[0].get(i + self.unit)
if s is not None: return s
return f"{_digits[self.value]} {_units[self.unit]}"
def parse(n):
digits = [int(d) for d in list(str(n))]
last_index = len(digits) - 1
v_nums = [str(VNum(digit, last_index - index, digits[index-1] if index > 0 else None, digits[index+1] if index < last_index else None)) for index, digit in enumerate(digits)]
v_nums = [num for num in v_nums if num != '']
return ' '.join(v_nums)