

I just finished project euler #17. Iโll go through my thought process in solving it here, but would love feedback, especially if your solution was different than mine. Iโm sure there are many more elegant and simplistic solutions.
The problem goes as follows:
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.
My first thought was that I would need to loop over the numbers 1 to 1000 and convert each number into the written word corresponding to that number.
Naturally, I could just make an array containing every written word. But I didnโt want to have to write every number. Instead, I thought about doing something like this:
Without defining every letter, I could make an array of the numbers 1 through 9, and then another array of the letters โoneโ through โnineโ.
If, for example, the number is 547, then I could see if the first number of the given number set matches any numbers from the onesArr. Then I could do the same for the last number. Once it finds a match, Iโll simply grab the value of the onesComp array instead, but at the same index where I found the match in the onesArr.
Although, this wouldnโt work for โtwentyโ, โthirtyโ, โfortyโ etc. It also wouldnโt work with 10 through 19. So, I could make a couple of additional arrays, and do the same thing, depending on the length of the given number.
Something like this would allow me to have a number array for 1โ10, and a matching word array for โoneโ-โtenโ. Then the same thing for teens, and tens. The key for me, is having the index values match. So my ones array starts at 1 instead of 0, since we arenโt using zero, and my teens array does include a zero, since that starts at 10, and Iโll be looking for the 0 in the number 10, just like Iโll be looking for the 1 in 11 and the 2 in 12, etc. Then the tens array starts with 2 and twenty. At that point, the next obstacle would be to determine the length of the number. My thought there would be to loop over the array of 1 to 1000. For each item, I would turn the number into a string and then split the string, so it would give me an array of each number. Then, inside and if statement, I would use parseInt() to convert it back into a number and check it against the value of the compare array. That part would probably look something like this:
Hereโs the final code:
let ones = ['one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine'];
let teens = ['ten', 'eleven', 'twelve', 'thirteen', 'fourteen', 'fifteen', 'sixteen', 'seventeen', 'eighteen', 'nineteen'];
let tens = ['twenty', 'thrity', 'forty', 'fifty', 'sixty', 'seventy', 'eighty', 'ninety'];
let thousands = ['thousand'];
let compareOnes = [1,2,3,4,5,6,7,8,9];
let compareTeens = [0,1,2,3,4,5,6,7,8,9];
let compareTens = [2,3,4,5,6,7,8,9];
let numbers = [];
for (var i = 1; i <= 1000; i++) {
numbers.push(i);
}
let currentCount = 0;
for (var i = 0; i < numbers.length; i++) {
let numStr = numbers[i].toString();
let numStrArr = numStr.split("");
if(numStrArr.length == 1){
let digit1 = parseInt(numStrArr[0]);
let index = compareOnes.indexOf(digit1);
currentCount = currentCount + ones[index];
}
if(numStrArr.length == 2 && numbers[i]>=20){
let digit1 = parseInt(numStrArr[0]);
let digit2 = parseInt(numStrArr[1]);
let index = compareTens.indexOf(digit1);
let index2 = compareOnes.indexOf(digit2);
currentCount = currentCount + tens[index] + ones[index2];
}
if(numStrArr.length == 2 && numbers[i]<20){
let digit2 = parseInt(numStrArr[1]);
let index2 = compareTeens.indexOf(digit2);
currentCount = currentCount + teens[index2];
}
if(numStrArr.length == 3 && numStrArr[1] == "0" && numStrArr[2] == "0"){
let digit1 = parseInt(numStrArr[0]);
let digit2 = parseInt(numStrArr[1]);
let digit3 = parseInt(numStrArr[2]);
let index3 = compareOnes.indexOf(digit1);
let index2 = compareTens.indexOf(digit2);
let index = compareOnes.indexOf(digit3);
currentCount = currentCount + ones[index3]+"hundred";
}
if(numStrArr.length == 3 && numStrArr[1] == "0" && numStrArr[2] !== "0"){
let digit1 = parseInt(numStrArr[0]);
let digit2 = parseInt(numStrArr[1]);
let digit3 = parseInt(numStrArr[2]);
let index3 = compareOnes.indexOf(digit1);
let index2 = compareTens.indexOf(digit2);
let index = compareOnes.indexOf(digit3);
currentCount = currentCount + ones[index3]+"hundred"+"and"+tens[index2]+ones[index];
}
if(numStrArr.length == 3 && numStrArr[1] == "1"){
let digit1 = parseInt(numStrArr[0]);
let digit2 = parseInt(numStrArr[1]);
let digit3 = parseInt(numStrArr[2]);
let index3 = compareOnes.indexOf(digit1);
let index2 = compareTeens.indexOf(digit3);
currentCount = currentCount + ones[index3]+"hundred"+"and"+teens[index2];
}
if(numStrArr.length == 3 && numStrArr[1] !== "0" && numStrArr[2] !== "0" && numStrArr[1] !== "1"){
let digit1 = parseInt(numStrArr[0]);
let digit2 = parseInt(numStrArr[1]);
let digit3 = parseInt(numStrArr[2]);
let index3 = compareOnes.indexOf(digit1);
let index2 = compareTens.indexOf(digit2);
let index = compareOnes.indexOf(digit3);
currentCount = currentCount + ones[index3]+"hundred"+"and"+tens[index2]+ones[index];
}
if(numStrArr.length == 3 && numStrArr[1] !== "0" && numStrArr[2] == "0" && numStrArr[1] !== "1"){
let digit1 = parseInt(numStrArr[0]);
let digit2 = parseInt(numStrArr[1]);
let digit3 = parseInt(numStrArr[2]);
let index3 = compareOnes.indexOf(digit1);
let index2 = compareTens.indexOf(digit2);
let index = compareOnes.indexOf(digit3);
currentCount = currentCount + ones[index3]+"hundred"+"and"+tens[index2];
}
if(numStrArr.length == 4){
currentCount = currentCount + "one"+"thousand";
}
}
let newCurrent = currentCount.replace(/undefined/g, "");
console.log(newCurrent);
console.log(newCurrent.length)
You may notice my bit of regex at the bottom there. I kept having undefined come up, and it was just added in there. I could have tried to figure out why, but it was obvious that all the other words I needed were still in there, so I just wrote a bit of regex to get rid of any undefined in the final string.
Hereโs what the final string looks likeโฆwell, just the first 75 numbers:
onetwothreefourfivesixseveneightnineteneleventwelvethirteenfourteenfifteensixteenseventeeneighteennineteentwentytwentyonetwentytwotwentythreetwentyfourtwentyfivetwentysixtwentyseventwentyeighttwentyninethritythrityonethritytwothritythreethrityfourthrityfivethritysixthrityseventhrityeightthrityninefortyfortyonefortytwofortythreefortyfourfortyfivefortysixfortysevenfortyeightfortyninefiftyfiftyonefiftytwofiftythreefiftyfourfiftyfivefiftysixfiftysevenfiftyeightfiftyninesixtysixtyonesixtytwosixtythreesixtyfoursixtyfivesixtysixsixtysevensixtyeightsixtynineseventyseventyoneseventytwoseventythreeseventyfourseventyfive
Create your free account to unlock your custom reading experience.