Number Letter Counts
If the numbers to are written out in words: one, two, three, four, five, then there are letters used in total.
If all the numbers from to (one thousand) inclusive were written out in words, how many letters would be used?
NOTE: Do not count spaces or hyphens. For example, (three hundred and forty-two) contains letters and (one hundred and fifteen) contains letters. The use of "and" when writing out numbers is in compliance with British usage.
Implementations
// Answer: 21124
#include <iostream>
template <int n> int count_letter(){ // TODO: We could do deeper: count_letter<int n, int demo> (<,10><,100>etc.) // ..but that might scare some folk and gain...nothing int x = 0; if( n < 100 ){ return count_letter<(n/10)*10>() + count_letter<n%10>(); }
x = (count_letter<n/100>()+7);//+count_letter<100>()); if( 0 != (n%100)){ x += 3 + count_letter<n-((n/100)*100)>(); } return x;}
template <> int count_letter<0>(){return 0;}template <> int count_letter<1>(){return 3;} // onetemplate <> int count_letter<2>(){return 3;} // twotemplate <> int count_letter<3>(){return 5;} // threetemplate <> int count_letter<4>(){return 4;} // fourtemplate <> int count_letter<5>(){return 4;} // fivetemplate <> int count_letter<6>(){return 3;} // sixtemplate <> int count_letter<7>(){return 5;} // seventemplate <> int count_letter<8>(){return 5;} // eighttemplate <> int count_letter<9>(){return 4;} // ninetemplate <> int count_letter<10>(){return 3;} // tentemplate <> int count_letter<11>(){return 6;} // eleventemplate <> int count_letter<12>(){return 6;} // twelvetemplate <> int count_letter<13>(){return 8;} // thirteentemplate <> int count_letter<14>(){return 8;} // fourteentemplate <> int count_letter<15>(){return 7;} // fifteentemplate <> int count_letter<16>(){return 7;} // sixteentemplate <> int count_letter<17>(){return 9;} // seventeentemplate <> int count_letter<18>(){return 8;} // eighteentemplate <> int count_letter<19>(){return 8;} // nineteentemplate <> int count_letter<20>(){return 6;} // twentytemplate <> int count_letter<30>(){return 6;} // thirtytemplate <> int count_letter<40>(){return 5;} // fortytemplate <> int count_letter<50>(){return 5;} // fiftytemplate <> int count_letter<60>(){return 5;} // sixtytemplate <> int count_letter<70>(){return 7;} // seventytemplate <> int count_letter<80>(){return 6;} // eightytemplate <> int count_letter<90>(){return 6;} // ninetytemplate <> int count_letter<100>(){return 10;} // onehundredtemplate <> int count_letter<1000>(){return 11;} // onethousand
static int g_letter_count = 0;
template<int from,int to> struct mp_for{ void operator()() { g_letter_count += count_letter<from>(); mp_for<from+1,to>()(); }};
// Recursive template stoptemplate<int from> struct mp_for<from,from>{ void operator()(){};};
#if ! defined UNITTEST_MODEint main(int argc, char const *argv[]){ mp_for<1,1001>()(); // Template recursion stops at <1001,1001> std::cout << "Answer: " << g_letter_count << std::endl; return 0;}#endif // #if ! defined UNITTEST_MODESolution Notes
Mathematical Background
This problem requires converting numbers from 1 to 1000 into their English word representations and counting the letters used. The challenge lies in handling the British English convention of using “and” when writing numbers (e.g., “one hundred and fifteen” instead of “one hundred fifteen”).
The total letter count grows quadratically with the upper limit due to the increasing complexity of number representations. Numbers 1-99 follow relatively simple patterns, while 100-999 add “hundred” and “and” connectors, and 1000 requires special handling.
Algorithm Analysis
Number-to-words conversion: Implement functions that break down numbers into hundreds, tens, and units components, using lookup tables for word representations.
Letter counting: Convert each number to its word form, then count alphabetic characters while ignoring spaces and hyphens.
Approaches:
- Lookup table approach: Pre-compute word lengths for common number components (ones, teens, tens)
- String concatenation: Build word representations by combining components with appropriate connectors
- Template metaprogramming: Use compile-time computation (as seen in C++ implementation)
Time complexity is O(n) where n=1000, with constant-time operations per number. Space complexity is O(1) using fixed-size lookup tables.
Key Insights
- British English requires “and” between hundreds and tens/units (e.g., “one hundred and fifteen”)
- “One thousand” is written as two words but counted as one unit
- Hyphens in compound numbers (twenty-one, thirty-four) are ignored in counting
- The pattern repeats every 100 numbers with increasing hundreds prefixes
- Template metaprogramming provides compile-time optimization in C++
- Total letter count for 1-1000 is 21,124
Educational Value
This problem teaches:
- String manipulation and text processing
- Number system representation and conversion algorithms
- Handling special cases in algorithmic thinking
- The importance of precise problem requirements (British vs American English)
- Lookup table optimization techniques
- Modular code design with reusable number conversion functions
- When to use compile-time vs runtime computation