Project Euler: #17 - Number letter counts

Project Euler: #17 - Number letter counts

Problem

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.


Problem Description

Well, writing the numbers in words form and counting the number of alphabets used is our problem here. Looks interesting, right?!

Yeah, we have to write out all the numbers from 1 to 1000 in words. And count the total number of alphabets, ignoring spaces and hyphens.


Approach

Yes, this problem can be approached in N different ways.

The way I approached this(inspired by a freecodecamp article/video ๐Ÿ˜Ž) is to split the number into thousands, hundreds and tens. Convert the number to words, append it to a string and then count the number of alphabets using String.prototype.length.

The Hackerrank version of this problem is quite different. Their word spelling, using space and and rules vary too. The Numbers in their test cases are quite big - 0 <= N <= 1,000,000,000,000

For the Hackerrank solution, I used Map object in Javascript and split the given number in 100s before combining them with proper denominations like billion, million etc.

Note: Please note that the solution provided is only for learning purposes. Once you understand the problem, please try it on your own before referring to my solution below.


Solution

let words = {
    'units': ['', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine',
        'ten', 'eleven', 'twelve', 'thirteen', 'fourteen', 'fifteen', 'sixteen', 'seventeen', 'eighteen', 'nineteen'],
    'tenth': ['', 'ten', 'twenty', 'thirty', 'forty', 'fifty', 'sixty', 'seventy', 'eighty', 'ninety']
}

let numToWordsCount = (limit) => {

    let sum = 0;

    for (let i = 1; i <= limit; i++) {

        let num = i
        let numStr = ''

        let thousands = Math.floor(num / 1000)
        if (thousands > 0) {
            numStr = numStr + words['units'][thousands] + 'thousand'
            num = num - (thousands * 1000)
        }

        let hundreds = Math.floor(num / 100)
        if (hundreds > 0) {
            numStr = numStr + words['units'][hundreds] + 'hundred'
            num = num - (hundreds * 100)
            if (num > 0) {
                numStr = numStr + 'and'
            }
        }

        if (num < 20) {
            numStr = numStr + words['units'][num]
        } else {
           let tens = Math.floor(num / 10)
            numStr = numStr + words['tenth'][tens]
            num = num - (tens * 10)
            numStr = numStr + words['units'][num]
        }

        sum = sum + numStr.length
    }

    return sum
}

console.log(numToWordsCount(1000))

You can find my solution on GitHub 17

If you have any feedback, please leave it below.

If you have any suggestions to improve my code or another way to approach this problem, leave it in the comment.

For the other Project Euler Solutions, please follow the series Project Euler Solutions in JS.

Thank you!

Reference:

ย