Skip to content

Instantly share code, notes, and snippets.

@behitek
Last active May 7, 2019 04:23
Show Gist options
  • Save behitek/d29242ea1a8b999e5c4c8982a4599732 to your computer and use it in GitHub Desktop.
Save behitek/d29242ea1a8b999e5c4c8982a4599732 to your computer and use it in GitHub Desktop.
Chuyển số viết thành số đọc sử dụng C++/Python
// https://daynhauhoc.com/t/share-code-doc-so-thanh-chu-so-lon-bao-nhieu-cung-can-tat/62701/
#include <iostream>
#include <string>
#include <algorithm>
#include <exception>
#include <cassert>
#ifdef __unix__
#include <clocale>
#elif defined _WIN32 || defined _WIN64
#include <fcntl.h> //_O_WTEXT
#include <io.h> //_setmode()
#endif
const std::wstring CHU_SO[] = {
L"không", L"một", L"hai", L"ba", L"bốn",
L"năm", L"sáu", L"bảy", L"tám", L"chín"
};
const std::wstring MUOIF = L"mười"; //muoi` co' dau'
const std::wstring MUOI = L"mươi";
const std::wstring TRAM = L"trăm";
const std::wstring NGAN_TR[] = { L"nghìn", L"triệu" };
const std::wstring TY = L"tỷ";
const std::wstring MOTS = L"mốt"; //mot' co dau sac
const std::wstring TU = L"tư"; //tu
const std::wstring LAM = L"lăm"; //lam
const std::wstring LINH = L"linh";
const wchar_t SPACE = L' ';
const std::wstring COMMA = L", ";
std::wstring toVnStr(const std::string& num);
int main()
{
#ifdef __unix__
setlocale(LC_ALL, "");
#elif defined _WIN32 || defined _WIN64
setmode(fileno(stdout), _O_WTEXT); //needed for output
setmode(fileno(stdin), _O_WTEXT); //needed for input
#endif
for (int i = 0; i < 1000; i++){
std::string s = std::to_string(i);
std::wcout << s.c_str() << " = " << toVnStr(s) << "\n";
}
}
std::wstring toVnStrLt100(const std::string& num)
{
if (num.size() == 1) return CHU_SO[num[0] - '0'];
auto result = num[0] == '1' ? MUOIF : (CHU_SO[num[0] - '0'] + SPACE + MUOI);
if (num[1] == '0') return result;
result += SPACE;
if (num[1] == '1' && num[0] != '1') result += MOTS;
else if (num[1] == '4' && num[0] != '1') result += TU;
else if (num[1] == '5') result += LAM;
else result += CHU_SO[num[1] - '0'];
return result;
}
std::wstring toVnStrLt1000(const std::string& num)
{
if (num.size() < 3) return toVnStrLt100(num);
auto result = CHU_SO[num[0] - '0'] + SPACE + TRAM;
if (num[1] == '0' && num[2] == '0') //[0-9]00
return num[0] == '0' ? std::wstring{} : result;
if (num[1] == '0') //[1-9]0[1-9]
return result + SPACE + LINH + SPACE + CHU_SO[num[2] - '0'];
return result + SPACE + toVnStrLt100(num.substr(1));
}
std::wstring toVnStrLt1e9(const std::string& num)
{
if (num.size() < 4) return toVnStrLt1000(num);
int splitIndex = num.size() % 3;
if (!splitIndex) splitIndex = 3;
auto left = toVnStrLt1e9(num.substr(0, splitIndex));
auto right = toVnStrLt1e9(num.substr(splitIndex));
if (left.empty() && right.empty()) return std::wstring{};
auto const& hang = NGAN_TR[(num.size() - splitIndex) / 3 - 1];
if (left.empty()) return CHU_SO[0] + SPACE + hang + SPACE + right;
if (right.empty()) return left + SPACE + hang;
return left + SPACE + hang + SPACE + right;
}
std::wstring toVnStrAbitrary(const std::string& num)
{
if (num.size() < 10) return toVnStrLt1e9(num);
int splitIndex = num.size() % 9;
if (!splitIndex) splitIndex = 9;
auto left = toVnStrLt1e9(num.substr(0, splitIndex));
auto right = toVnStrAbitrary(num.substr(splitIndex));
if (left.empty()) return right;
auto hang = TY;
for (auto i = (num.size() - splitIndex) / 9; i-->1; hang += SPACE + TY);
if (right.empty()) return left + SPACE + hang;
return left + SPACE + hang + COMMA + right;
}
std::string stripZeros(const std::string& s, size_t z=0)
{
while (z < s.size() && s[z] == '0') ++z;
return s[z-1] == '0' ? s.substr(z) : s;
}
std::wstring toVnStr(const std::string& num)
{
if (std::any_of(begin(num), end(num), [](auto c) { return !isdigit(c); }))
throw std::invalid_argument("Input string must consist of digits (0-9) only.");
auto s = stripZeros(num);
return toVnStrAbitrary(s.empty() ? "0" : s);
}
# https://daynhauhoc.com/t/share-code-doc-so-thanh-chu-so-lon-bao-nhieu-cung-can-tat/62701/
class NumToVnStr:
def __init__(self, mươi='mươi', nghìn='nghìn', tư='tư', lăm='lăm', linh='linh', tỷ='tỷ', đọc_số_rỗng=True):
self.chữ_số = ('không', 'một', 'hai', 'ba', 'bốn', 'năm', 'sáu', 'bảy', 'tám', 'chín', 'mười')
self.mươi = mươi
self.trăm = 'trăm'
self.nghìn = nghìn
self.triệu = 'triệu'
self.tỷ = tỷ
self.mốt = 'mốt'
self.tư = tư
self.lăm = lăm
self.linh = linh
self.đọc_số_rỗng = đọc_số_rỗng
def to_vn_str(self, s):
return self._arbitrary(s.lstrip('0'))
def _int(self, c):
return ord(c) - ord('0') if c else 0
def _LT1e2(self, s):
if len(s) <= 1: return self.chữ_số[self._int(s)]
if s[0] == '1':
ret = self.chữ_số[10]
else:
ret = self.chữ_số[self._int(s[0])]
if self.mươi: ret += ' ' + self.mươi
elif s[1] == '0': ret += ' mươi'
if s[1] != '0':
ret += ' '
if s[1] == '1' and s[0] != '1': ret += self.mốt
elif s[1] == '4' and s[0] != '1': ret += self.tư
elif s[1] == '5': ret += self.lăm
else: ret += self.chữ_số[self._int(s[1])]
return ret
def _LT1e3(self, s):
if len(s) <= 2: return self._LT1e2(s)
if s == '000': return ''
ret = self.chữ_số[self._int(s[0])] + ' ' + self.trăm
if s[1] != '0':
ret += ' ' + self._LT1e2(s[1:])
elif s[2] != '0':
ret += ' ' + self.linh + ' ' + self.chữ_số[self._int(s[2])]
return ret
def _LT1e9(self, s):
if len(s) <= 3: return self._LT1e3(s)
if s == '000000' or s == '000000000': return ''
mid = len(s) % 3 if len(s) % 3 else 3
left, right = self._LT1e3(s[:mid]), self._LT1e9(s[mid:])
hang = self.nghìn if len(s) <= 6 else self.triệu
if not left:
if not self.đọc_số_rỗng: return right
else: return self.chữ_số[0] + ' ' + hang + ' ' + right
if not right: return left + ' ' + hang
return left + ' ' + hang + ' ' + right
def _arbitrary(self, s):
if len(s) <= 9: return self._LT1e9(s)
mid = len(s) % 9 if len(s) % 9 else 9
left, right = self._LT1e9(s[:mid]), self._arbitrary(s[mid:])
hang = ' '.join([self.tỷ] * ((len(s) - mid) // 9))
if not left:
if not self.đọc_số_rỗng: return right
elif right: return self.chữ_số[0] + ' ' + hang + ', ' + right
else: return right
if not right: return left + ' ' + hang
return left + ' ' + hang + ', ' + right
if __name__ == '__main__':
test_cases_1 = (
"0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
"10", "11", "12", "20", "21", "22", "24", "90", "91", "97",
"300", "999", "121", "215", "5121", "39500",
"1025217", "51105500", "51000000", "999999999",
"5120625952200", "12000000000000000000", "18446744073709551615",
"18000000000709551615", "11000000000",
"1000015", "1002015", "1000000024",
"03215", "", "0000", "00001", "00100",
"1844674407370955161518000000000000000000709551615",
"0321", "000345", "15", "40430203", "3209", "3500", "3901", "21",
"3005", "3055", "9031", "9330",
"9000005", "9001005",
)
test_cases_2 = (
("32000000", "ba mươi hai triệu"),
("32516000", "ba mươi hai triệu năm trăm mười sáu nghìn"),
("32516497", "ba mươi hai triệu năm trăm mười sáu nghìn bốn trăm chín mươi bảy"),
("834291712", "tám trăm ba mươi tư triệu hai trăm chín mươi mốt nghìn bảy trăm mười hai"),
("308250705", "ba trăm linh tám triệu hai trăm năm mươi nghìn bảy trăm linh năm"),
("500209037", "năm trăm triệu hai trăm linh chín nghìn không trăm ba mươi bảy"),
("7312836", "bảy triệu ba trăm mười hai nghìn tám trăm ba mươi sáu"),
("57602511", "năm mươi bảy triệu sáu trăm linh hai nghìn năm trăm mười một"),
("351600307", "ba trăm năm mươi mốt triệu sáu trăm nghìn ba trăm linh bảy"),
("900370200", "chín trăm triệu ba trăm bảy mươi nghìn hai trăm"),
("400070192", "bốn trăm triệu không trăm bảy mươi nghìn một trăm chín mươi hai"),
("10250214", "mười triệu hai trăm năm mươi nghìn hai trăm mười bốn"),
("253564888", "hai trăm năm mươi ba triệu năm trăm sáu mươi tư nghìn tám trăm tám mươi tám"),
("400036105", "bốn trăm triệu không trăm ba mươi sáu nghìn một trăm linh năm"),
("700000231", "bảy trăm triệu không nghìn hai trăm ba mươi mốt"),
)
custom_converter = NumToVnStr(đọc_số_rỗng=True, linh='lẻ', tư='bốn', nghìn='ngàn', mươi=False, tỷ='tỉ', lăm='nhăm')
for i in test_cases_1:
print('{} = {}'.format(i, custom_converter.to_vn_str(i)))
default_converter = NumToVnStr()
for test_case in test_cases_2:
i, o = test_case
assert default_converter.to_vn_str(i) == o
print('\n{}\n{}\n{}'.format(i, default_converter.to_vn_str(i), o))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment