Tim Varley Logo
Tim Varley Principal AI Engineer and Tech Leader
Problem #17 medium

Number Letter Counts

If the numbers 11 to 55 are written out in words: one, two, three, four, five, then there are 3+3+5+4+4=193 + 3 + 5 + 4 + 4 = 19 letters used in total.

If all the numbers from 11 to 10001000 (one thousand) inclusive were written out in words, how many letters would be used?

NOTE: Do not count spaces or hyphens. For example, 342342 (three hundred and forty-two) contains 2323 letters and 115115 (one hundred and fifteen) contains 2020 letters. The use of "and" when writing out numbers is in compliance with British usage.

View on Project Euler

Implementations

cpp
// 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;} // one
template <> int count_letter<2>(){return 3;} // two
template <> int count_letter<3>(){return 5;} // three
template <> int count_letter<4>(){return 4;} // four
template <> int count_letter<5>(){return 4;} // five
template <> int count_letter<6>(){return 3;} // six
template <> int count_letter<7>(){return 5;} // seven
template <> int count_letter<8>(){return 5;} // eight
template <> int count_letter<9>(){return 4;} // nine
template <> int count_letter<10>(){return 3;} // ten
template <> int count_letter<11>(){return 6;} // eleven
template <> int count_letter<12>(){return 6;} // twelve
template <> int count_letter<13>(){return 8;} // thirteen
template <> int count_letter<14>(){return 8;} // fourteen
template <> int count_letter<15>(){return 7;} // fifteen
template <> int count_letter<16>(){return 7;} // sixteen
template <> int count_letter<17>(){return 9;} // seventeen
template <> int count_letter<18>(){return 8;} // eighteen
template <> int count_letter<19>(){return 8;} // nineteen
template <> int count_letter<20>(){return 6;} // twenty
template <> int count_letter<30>(){return 6;} // thirty
template <> int count_letter<40>(){return 5;} // forty
template <> int count_letter<50>(){return 5;} // fifty
template <> int count_letter<60>(){return 5;} // sixty
template <> int count_letter<70>(){return 7;} // seventy
template <> int count_letter<80>(){return 6;} // eighty
template <> int count_letter<90>(){return 6;} // ninety
template <> int count_letter<100>(){return 10;} // onehundred
template <> 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 stop
template<int from> struct mp_for<from,from>
{
void operator()(){};
};
#if ! defined UNITTEST_MODE
int 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_MODE
View on GitHub
O(n) time complexity

Solution 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