80 lines
1.6 KiB
C++
80 lines
1.6 KiB
C++
#include "say.h"
|
|
|
|
#include <stdexcept>
|
|
#include <unordered_map>
|
|
|
|
|
|
namespace say {
|
|
|
|
using namespace std;
|
|
|
|
namespace {
|
|
|
|
const unordered_map<number_t, string> number_map = {
|
|
{0, "zero"},
|
|
{1, "one"},
|
|
{2, "two"},
|
|
{3, "three"},
|
|
{4, "four"},
|
|
{5, "five"},
|
|
{6, "six"},
|
|
{7, "seven"},
|
|
{8, "eight"},
|
|
{9, "nine"},
|
|
{10, "ten"},
|
|
{11, "eleven"},
|
|
{12, "twelve"},
|
|
{13, "thirteen"},
|
|
{20, "twenty"},
|
|
{30, "thirty"},
|
|
{40, "forty"},
|
|
{50, "fifty"},
|
|
{80, "eighty"}
|
|
};
|
|
|
|
struct order_t
|
|
{
|
|
number_t divisor;
|
|
number_t max;
|
|
string separator;
|
|
string suffix;
|
|
};
|
|
|
|
const order_t orders[] = {
|
|
{10, 100, "-", "ty"},
|
|
{100, 1000, " ", " hundred"},
|
|
{1000, 1000000, " ", " thousand"},
|
|
{1000000, 1000000000, " ", " million"},
|
|
{1000000000, 1000000000000, " ", " billion"}
|
|
};
|
|
|
|
}
|
|
|
|
|
|
string in_english(number_t number)
|
|
{
|
|
if (number_map.count(number))
|
|
return number_map.at(number);
|
|
|
|
if (number > 13 && number < 20)
|
|
return number_map.at(number - 10) + "teen";
|
|
|
|
for (auto o : orders) {
|
|
|
|
if (number >= o.divisor && number < o.max) {
|
|
|
|
if (number % o.divisor == 0)
|
|
return in_english(number / o.divisor) + o.suffix;
|
|
|
|
number_t reminder = number % o.divisor;
|
|
number_t div_part = number - reminder;
|
|
|
|
return in_english(div_part) + o.separator + in_english(reminder);
|
|
}
|
|
}
|
|
|
|
throw domain_error("can't say the number");
|
|
}
|
|
|
|
|
|
}
|