# Project Euler Problem 17 Solution

## Question

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.

## JavaScript

const ones = {
1: 'one',
2: 'two',
3: 'three',
4: 'four',
5: 'five',
6: 'six',
7: 'seven',
8: 'eight',
9: 'nine',
10: 'ten',
11: 'eleven',
12: 'twelve',
13: 'thirteen',
14: 'fourteen',
15: 'fifteen',
16: 'sixteen',
17: 'seventeen',
18: 'eighteen',
19: 'nineteen'
}

const tens = {
2: 'twenty',
3: 'thirty',
4: 'forty',
5: 'fifty',
6: 'sixty',
7: 'seventy',
8: 'eighty',
9: 'ninety'
}

function english(number) {
let parts = []

if (number >= 1000) {
parts.push(ones[Math.floor(number / 1000)])
parts.push("thousand")
number %= 1000
}

if (number >= 100) {
parts.push(ones[Math.floor(number / 100)])
parts.push("hundred")
if (number % 100 !== 0) {
parts.push("and")
}
number %= 100
}

if (number >= 20) {
parts.push(tens[Math.floor(number / 10)])
number %= 10
}

if (ones[number]) {
parts.push(ones[number])
}

return parts.join("")
}

const words = []
for (let i = 1; i <= 1000; i++) {
words.push(english(i))
}
console.log(words.join("").length)
$time node --use-strict english-numbers.js real 0m0.054s user 0m0.055s sys 0m0.000s ## Python #!/usr/bin/env python def to_english(number): _ones = { 1: 'one', 2: 'two', 3: 'three', 4: 'four', 5: 'five', 6: 'six', 7: 'seven', 8: 'eight', 9: 'nine', 10: 'ten', 11: 'eleven', 12: 'twelve', 13: 'thirteen', 14: 'fourteen', 15: 'fifteen', 16: 'sixteen', 17: 'seventeen', 18: 'eighteen', 19: 'nineteen', } _tens = { 2: 'twenty', 3: 'thirty', 4: 'forty', 5: 'fifty', 6: 'sixty', 7: 'seventy', 8: 'eighty', 9: 'ninety' } if abs(number) >= 10000: return str(number) elif number == 0: return 'zero' else: output = '' if number < 0: output += 'negative ' number = abs(number) if number >= 1000: output += _ones[number // 1000] if number % 1000 == 0: output += " thousand" else: output += " thousand " number %= 1000 if number >= 100: output += _ones[number // 100] if number % 100 == 0: output += " hundred" else: output += " hundred and " number %= 100 if number >= 20: output += _tens[number // 10] number %= 10 if number % 10 in _ones: output += '-' if number in _ones: output += _ones[number] return output def cleanse_string(string): '''remove spaces and hyphens''' string = string.replace(' ', '') string = string.replace('-', '') return string print(sum(len(cleanse_string(to_english(i))) for i in range(1, 1001))) $ time python3 num-string-sum.py
real   0m0.019s
user   0m0.019s
sys    0m0.000s

## Ruby

#!/usr/bin/env ruby
require 'linguistics' # gem install linguistics
Linguistics::use( :en )
puts (1..1000).map { |i| i.en.numwords.gsub(/[ -]/, '').length }.reduce(:+)
\$ time ruby number-to-words.rb
real   0m0.130s
user   0m0.123s
sys    0m0.008s