Hackernoon logoprojecteuler.net # 17 by@ethan.jarrell

projecteuler.net # 17

Author profile picture

@ethan.jarrellEthan Jarrell

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

Tags

Join Hacker Noon

Create your free account to unlock your custom reading experience.