exercism-solutions/cpp/say/say.cpp

81 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");
}
}