#include <iostream>
#include <string>

const std::string NUMSPL1[] = {
    "zero", "one", "two", "three", "four", "five", "six",
    "seven", "eight", "nine", "ten", "eleven", "twelve",
    "thirteen", "fourteen", "fifteen", "sixteen",
    "seventeen", "eighteen", "nineteen"
};
const std::string NUMSPL2[] = {
    "twenty", "thirty", "forty", "fifty", "sixty",
    "seventy", "eighty", "ninety"
};
const std::string NUMSPL3[] = {
    "hundred", "thousand", "million", "billion", "trillion",
    "quadrillion", "quintillion", "sextillion", "septillion",
    "octillion", "nonillion", "decillion", "undecillion",
    "duodecillion", "tredecillion", "quattuordecillion", "quindecillion",
    "sexdecillion", "septendecillion", "octodecillion", "novemdecillion",
    "vigintillion"
};

std::string numSp(const std::string& num);

int main()
{
    std::cout << "0" << ": " << numSp("0") << ".\n\n"
              << "13" << ": " << numSp("13") << ".\n\n"
              << "218" << ": " << numSp("218") << ".\n\n"
              << "1204" << ": " << numSp("1204") << ".\n\n"
              << "10009" << ": " << numSp("10009") << ".\n\n"
              << "023.456.951.743.236.125.000.012.000" << ":\n"
              << numSp("023456951743236125000012000") << ".\n\n"
              << "777.777.777.777.777.777.777.777.777.777.777.777.777.777.777."
            "777.777.777.777.777.777.777" ":\n"
              << numSp("777777777777777777777777777777777777777777777777777777"
                  "777777777777")  << ".\n\n";
}

std::string removeLeadingZeros(const std::string& n)
{
    std::string result = "0";
    if (n.length() == 1) {
        result = n;
    } else if (n.length() > 1) {
        for (size_t i = 0; i < n.length(); ++i)
            if (n[i] != '0') {
                result = n.substr(i);
                break;
            }
    }
    return result;
}

std::string numSpLt100(const std::string& num)
{
    std::string n = removeLeadingZeros(num);
    std::string result = "";
    if (n.length() == 1) {
        result = NUMSPL1[n[0] - '0'];
    } else if (n.length() == 2) {
        if (n[0] == '1') {
            result = NUMSPL1[n[1] - '0' + 10];
        } else {
            result = NUMSPL2[n[0] - '2'];
            if (n[1] != '0') result += " " + NUMSPL1[n[1] - '0'];
        }
    }
    return result;
}

std::string numSpLt1000(const std::string& num)
{
    std::string n = removeLeadingZeros(num);
    std::string result = "";
    if (n.length() == 1 || n.length() == 2) {
        result = numSpLt100(n);
    } else if (n.length() == 3) {
        std::string lt100 = numSpLt100(n.substr(1));
        result = NUMSPL1[n[0] - '0'] + " " + NUMSPL3[0];
        if (lt100 != NUMSPL1[0]) result += " " + lt100;
    }
    return result;
}

std::string numSp(const std::string& num)
{
    std::string n = removeLeadingZeros(num);
    std::string res = "";
    if (n.length() <= 3) {
        res = numSpLt1000(n);
    } else if (n.length() <= 66) {
        int t = 1;
        res = numSpLt1000(n.substr(n.length() - 3));
        if (res == NUMSPL1[0]) res = "";
        while (n.length() - 3*t > 3)
        {
            std::string tmp = numSpLt1000( n.substr(n.length()-3*++t, 3) );
            if (tmp != NUMSPL1[0])
                res = tmp + " " + NUMSPL3[t-1] + (res!="" ? ", " : "") + res;
        }
        res = numSpLt1000( n.substr(0, n.length() - 3*t) ) + " " +
                 NUMSPL3[t] + (res!="" ? ", " : "") + res;
    }
    return res;
}