## Project Euler Problem 17

14 04 2009

Here’s a problem to make you shudder at the lack of logic in the English language.

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

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

NOTE: Do not count spaces or hyphens. For example, 342 (three hundred and forty-two) contains 23 letters and 115 (one hundred and fifteen) contains 20 letters. The use of “and” when writing out numbers is in compliance with British usage.

First I put together a table of the words I’ll be using and counts of letters in them.

One     3 ten           3 eleven      6

Two    3 twenty   6 twelve       6

Three 5 thirty      6 thirteen   8

Four  4 forty        5 fortteen   8

Five   4 fifty          5 fifteen        7

Six      3 sixty       5 sixteen        7

Seven 5 seventy 7 seventeen 9

Eight  5 eighty     6 eighteen     8

Nine   4 ninety     6 nineteen    8

and 3

hundred 7

thousand 8

From here on, it’s time to get to some coding. I decided to throw something together in TCL using lists rather than bothering with C (although, in this case, the code isn’t really much shorter).

There’s basically two ways to do it, either deal with words, or deal with numbers. The former you could just write a function to convert a number to it’s English equivalent and then count the number of letters in it for each number between 1 and 1,000. The latter method, which I chose, dealed with the pure numbers by using a bunch of for loops. It’s sort of ugly, but it works.

set teenlist [list 3 6 6 8 8 7 7 9 8 8]
set oneslist [list 3 3 5 4 4 3 5 5 4]
set tenslist [list 6 6 5 5 5 7 6 6]

# 1 – 19
set lettersum 0
foreach one \$oneslist {
set lettersum [expr \$lettersum + \$one]
}
foreach teen \$teenlist {
set lettersum [expr \$lettersum + \$teen]
}

# 20-99
foreach ten \$tenslist {
set lettersum [expr \$lettersum + \$ten]
foreach one \$oneslist {
set lettersum [expr \$lettersum + \$ten + \$one]
}
}

# 100 – 999
foreach hundred \$oneslist {
# 100, 200, …, 300
set lettersum [expr \$lettersum + \$hundred + 7]

# 101-109, 201-209, …, 901-909
foreach one \$oneslist {
set lettersum [expr \$lettersum + \$hundred + 10 + \$one]
}

# 110-119, 210-219, …, 910-919
foreach teen \$teenlist {
set lettersum [expr \$lettersum + \$hundred + 10 + \$teen]
}

# 120-199, 220-299, …, 920-999
foreach ten \$tenslist {
set lettersum [expr \$lettersum + \$hundred + 10 + \$ten]
foreach one \$oneslist {
set lettersum [expr \$lettersum + \$hundred + 10 + \$ten + \$one]
}
}
}

#1,000
set lettersum [expr \$lettersum + 11]

puts \$lettersum

I think I could have done it with paper and pencil faster than it took me to write the code though…