Euler Problem 17: Number Letter Counts

Euler Problem 17: written numbersEuler Problem 17 asks to count the letters in numbers written as words. This is a skill we all learnt in primary school mainly useful when writing cheques—to those that still use them.

Each language has its own rules for writing numbers. My native language Dutch has very different logic to English. Both Dutch and English use compound words after the number twelve.

Linguists have theorised this is evidence that early Germanic numbers were duodecimal. This factoid is supported by the importance of a “dozen” as a counting word and the twelve hours in the clock. There is even a Dozenal Society that promotes the use of a number system based on 12.

The English language changes the rules when reaching the number 21. While we say eight-teen in English, we do no say “one-twenty”. Dutch stays consistent and the last number is always spoken first. For example, 37 in English is “thirty-seven”, while in Dutch it is written as “zevenendertig” (seven and thirty).

Euler Problem 17 Definition

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.

Solution

The first piece of code provides a function that generates the words for numbers 1 to 999,999. This is more than the problem asks for, but it might be a useful function for another application. The last line concatenates all words together and removes the spaces.

numword.en <- function(x) { if (x > 999999) return("Error: Oustide my vocabulary")
    # Vocabulary 
    single <- c("one", "two", "three", "four", "five", "six", "seven", "eight", "nine")
    teens <- c( "ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen")
    tens <- c("ten", "twenty", "thirty", "forty", "fifty", "sixty", "seventy", "eighty", "ninety")
    # Translation
    numword.10 <- function (y) {
        a <- y %% 100
        if (a != 0) {
            and <- ifelse(y > 100, "and", "")
            if (a < 20)
                return (c(and, c(single, teens)[a]))
            else
                return (c(and, tens[floor(a / 10)], single[a %% 10]))
        }
    }
    numword.100 <- function (y) {
        a <- (floor(y / 100) %% 100) %% 10
        if (a != 0)
            return (c(single[a], "hundred"))
    }
    numword.1000 <- function(y) {
        a <- (1000 * floor(y / 1000)) / 1000
        if (a != 0)
            return (c(numword.100(a), numword.10(a), "thousand"))
    }
    numword <- paste(c(numword.1000(x), numword.100(x), numword.10(x)), collapse=" ")
    return (trimws(numword))
}

answer <- nchar(gsub(" ", "", paste0(sapply(1:1000, numword.en), collapse="")))
print(answer)

Writing Numbers in Dutch

I went beyond Euler Problem 17 by translating the code to spell numbers in Dutch. Interesting bit of trivia is that it takes 307 fewer characters to spell the numbers 1 to 1000 in Dutch than it does in English.

It would be good if other people can submit functions for other languages in the comment section. Perhaps we can create an R package with a multi-lingual function for spelling numbers.

numword.nl <- function(x) {
    if (x > 999999) return("Error: Getal te hoog.")
    single <- c("een", "twee", "drie", "vier", "vijf", "zes", "zeven", "acht", "negen")
    teens <- c( "tien", "elf", "twaalf", "dertien", "veertien", "fifteen", "zestien", "zeventien", "achtien", "negentien")
    tens <- c("tien", "twintig", "dertig", "veertig", "vijftig", "zestig", "zeventig", "tachtig", "negengtig")
    numword.10 <- function(y) {
        a <- y %% 100
        if (a != 0) {
            if (a < 20)
                return (c(single, teens)[a])
            else
                return (c(single[a %% 10], "en", tens[floor(a / 10)]))
        }
    }
    numword.100 <- function(y) {
        a <- (floor(y / 100) %% 100) %% 10
        if (a == 1)
            return ("honderd")
        if (a > 1) 
            return (c(single[a], "honderd"))
    }
    numword.1000 <- function(y) {
        a <- (1000 * floor(y / 1000)) / 1000
        if (a == 1)
            return ("duizend ")
        if (a > 0)
            return (c(numword.100(a), numword.10(a), "duizend "))
    }
    numword<- paste(c(numword.1000(x), numword.100(x), numword.10(x)), collapse="")
    return (trimws(numword))
}

antwoord <- nchar(gsub(" ", "", paste0(sapply(1:1000, numword.nl), collapse="")))
print(antwoord)

print(answer - antwoord)

View the latest version of this code on GitHub.

8 thoughts on “Euler Problem 17: Number Letter Counts

  1. I received an e-mail from Emrehan Zeybekoğlu who amended the code for the Turkish language. This language is more economic than both English and Dutch as it requires 7518 fewer characters.

    # Turkish number words
    # Emrehan Zeybekoğlu
    
    numword.tr &lt;- function(x) { if (x &gt; 999999) return(&quot;Error: Oustide my vocabulary&quot;)
        # Vocabulary 
        single &lt;- c(&quot;bir&quot;, &quot;iki&quot;, &quot;üç&quot;, &quot;dört&quot;, &quot;beş&quot;, &quot;altı&quot;, &quot;yedi&quot;, &quot;sekiz&quot;, &quot;dokuz&quot;)
        teens &lt;- c( &quot;on&quot;, &quot;onbir&quot;, &quot;oniki&quot;, &quot;onüç&quot;, &quot;ondört&quot;, &quot;onbeş&quot;, &quot;onaltı&quot;, &quot;onyedi&quot;, &quot;onsekiz&quot;, &quot;ondokuz&quot;)
        tens &lt;- c(&quot;on&quot;, &quot;yirmi&quot;, &quot;otuz&quot;, &quot;kırk&quot;, &quot;elli&quot;, &quot;altmış&quot;, &quot;yetmiş&quot;, &quot;seksen&quot;, &quot;doksan&quot;)
        # Translation
        numword.10 &lt;- function (y) {
            a &lt;- y %% 100
            if (a != 0) {
                if (a &lt; 20)
                    return (c(single, teens)[a])
                else
                    return (c(tens[floor(a / 10)], single[a %% 10]))
            }
        }
        numword.100 &lt;- function (y) {
            a &lt;- (floor(y / 100) %% 100) %% 10
            if (a != 0)
                return (c(single[a], &quot;yüz&quot;))
        }
        numword.1000 &lt;- function(y) {
            a &lt;- (1000 * floor(y / 1000)) / 1000
            if (a != 0)
                return (c(numword.100(a), numword.10(a), &quot;bin&quot;))
        }
        numword &lt;- paste(c(numword.1000(x), numword.100(x), numword.10(x)), collapse=&quot; &quot;)
        return (trimws(numword))
    }
    
    answer &lt;- nchar(gsub(&quot; &quot;, &quot;&quot;, paste0(sapply(1:1000, numword.tr), collapse=&quot;&quot;)))
    print(answer)
    
  2. Pingback: Euler Problem 17: Number Letter Counts – Mubashir Qasim

Feel free to share your thoughts about this article