#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <stdexcept>
class NumberSpeller {
private:
const std::vector<std::string> ones = {
"", "one", "two", "three", "four", "five",
"six", "seven", "eight", "nine"
};
const std::vector<std::string> teens = {
"ten", "eleven", "twelve", "thirteen", "fourteen",
"fifteen", "sixteen", "seventeen", "eighteen", "nineteen"
};
const std::vector<std::string> tens = {
"", "", "twenty", "thirty", "forty", "fifty",
"sixty", "seventy", "eighty", "ninety"
};
// Helper function to spell numbers 0-99
std::string spellTwoDigit(int n) {
if (n == 0) return "";
if (n < 10) return ones[n];
if (n < 20) return teens[n - 10];
int tensDigit = n / 10;
int onesDigit = n % 10;
if (onesDigit == 0) {
return tens[tensDigit];
}
return tens[tensDigit] + ones[onesDigit];
}
// Helper function to spell numbers 0-999
std::string spellThreeDigit(int n) {
if (n == 0) return "";
if (n < 100) return spellTwoDigit(n);
int hundreds = n / 100;
int remainder = n % 100;
std::string result = ones[hundreds] + "hundred";
if (remainder > 0) {
// Note: In US English, "and" is often omitted, but can be included
// For consistency with UK English, you could add "and" here
result += spellTwoDigit(remainder);
}
return result;
}
public:
std::string spellNumber(long long n) {
if (n < 1) {
throw std::invalid_argument("Number must be positive");
}
// Handle numbers up to 999 trillion (999,999,999,999,999)
if (n >= 1000000000000000LL) {
throw std::invalid_argument("Number too large (max: 999 trillion)");
}
if (n < 100) {
return spellTwoDigit(static_cast<int>(n));
}
std::vector<std::pair<long long, std::string>> scales = {
{1000000000000LL, "trillion"},
{1000000000LL, "billion"},
{1000000LL, "million"},
{1000LL, "thousand"},
{1LL, ""}
};
std::string result;
bool first = true;
for (const auto& [scale, name] : scales) {
if (n >= scale) {
int part = static_cast<int>(n / scale);
if (part > 0) {
if (!first) {
// Add separation between parts if needed
// In this implementation, we concatenate directly
}
result += spellThreeDigit(part);
if (!name.empty()) {
result += name;
}
first = false;
}
n %= scale;
}
}
return result;
}
int countLetters(const std::string& word) {
return std::count_if(word.begin(), word.end(),
[](char c) { return std::isalpha(c); });
}
};
class BeautifulNumberCounter {
private:
NumberSpeller speller;
public:
bool isBeautiful(long long num) {
try {
std::string spelling = speller.spellNumber(num);
int letterCount = speller.countLetters(spelling);
return letterCount > 0 && (num % letterCount == 0);
} catch (const std::exception&) {
return false;
}
}
long long countBeautifulNumbers(long long n) {
if (n < 1) {
throw std::invalid_argument("N must be positive");
}
long long count = 0;
for (long long i = 1; i <= n; ++i) {
if (isBeautiful(i)) {
count++;
}
}
return count;
}
std::vector<long long> getBeautifulNumbers(long long n) {
if (n < 1) {
throw std::invalid_argument("N must be positive");
}
std::vector<long long> beautifulNumbers;
for (long long i = 1; i <= n; ++i) {
if (isBeautiful(i)) {
beautifulNumbers.push_back(i);
}
}
return beautifulNumbers;
}
void printBeautifulNumberDetails(long long n) {
try {
std::string spelling = speller.spellNumber(n);
int letterCount = speller.countLetters(spelling);
bool beautiful = (n % letterCount == 0);
std::cout << n << ": '" << spelling << "' has " << letterCount
<< " letters, " << n << " % " << letterCount
<< " = " << (n % letterCount)
<< ", beautiful: " << (beautiful ? "true" : "false") << std::endl;
} catch (const std::exception& e) {
std::cout << n << ": Error - " << e.what() << std::endl;
}
}
};
int main() {
BeautifulNumberCounter counter;
NumberSpeller speller;
// Test the examples from the problem
std::cout << "Testing known examples:" << std::endl;
std::vector<long long> testCases = {4, 6, 12, 86};
for (long long num : testCases) {
counter.printBeautifulNumberDetails(num);
}
// Test some larger numbers
std::cout << "\nTesting larger numbers:" << std::endl;
std::vector<long long> largeTests = {100, 144, 200, 1000, 1200};
for (long long num : largeTests) {
counter.printBeautifulNumberDetails(num);
}
// Find all beautiful numbers from 1 to 99 (original problem)
std::cout << "\nFinding all beautiful numbers from 1 to 99:" << std::endl;
std::vector<long long> beautifulNumbers = counter.getBeautifulNumbers(99);
for (long long num : beautifulNumbers) {
std::string spelling = speller.spellNumber(num);
int letterCount = speller.countLetters(spelling);
std::cout << num << ": '" << spelling << "' (" << letterCount << " letters)" << std::endl;
}
// Test with various values of N
std::cout << "\nBeautiful numbers count for different values of N:" << std::endl;
std::vector<long long> testValues = {10, 20, 30, 40, 50, 60, 70, 80, 90, 99, 100, 150, 200};
for (long long n : testValues) {
long long count = counter.countBeautifulNumbers(n);
std::cout << "N = " << n << ": " << count << " beautiful numbers" << std::endl;
}
// Final answer for original problem
std::cout << "\nAnswer: There are " << counter.countBeautifulNumbers(99)
<< " beautiful numbers between 1 and 99" << std::endl;
// Example: Find beautiful numbers between 100 and 200
std::cout << "\nExample: Beautiful numbers between 100 and 200:" << std::endl;
std::vector<long long> beautiful100to200;
for (long long i = 100; i <= 200; ++i) {
if (counter.isBeautiful(i)) {
beautiful100to200.push_back(i);
}
}
std::cout << "Found " << beautiful100to200.size() << " beautiful numbers: ";
for (size_t i = 0; i < beautiful100to200.size(); ++i) {
if (i > 0) std::cout << ", ";
std::cout << beautiful100to200[i];
}
std::cout << std::endl;
return 0;
}