diff --git a/Project-Euler/Problem017.js b/Project-Euler/Problem017.js new file mode 100644 index 0000000000..14096b6ec6 --- /dev/null +++ b/Project-Euler/Problem017.js @@ -0,0 +1,117 @@ +/** + * Problem 17 - Number letter counts + * + * @see {@link https://projecteuler.net/problem=17} + * + * 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? + * + * @author Chetan07j + */ + +// Array of number word length from 0 -> 19 +const ones = [4, 3, 3, 5, 4, 4, 3, 5, 5, 4, 3, 6, 6, 8, 8, 7, 7, 9, 8, 8] + +// Array for tens from 20, 30, 40, 50, 60, 70, 80, 90 in words length +const tens = [6, 6, 5, 5, 5, 7, 6, 6] + +// Word length for words thousand, hundred, and +const thousandLength = 8 +const hundredLength = 7 +const andLength = 3 + +/** + * Function to convert number to word + * + * This function is called recursively to handle thousand and its sub part + */ +const numberToWordLength = (n) => { + let count = 0 + + // If number is < 20 then return its corresponding value from ones + if (n < 20) { + return ones[n] + } + + /** + * To calculate tens value "n / 10 - 2" is performed, which might return decimal value + * to extract proper integer value Math.floor is added + * Here "-2" is performed as our tens array start with index 0 + * To get appropriate value from that for our number it is required + * e.g., + * -> 34 -> 34/10= 3.4 -> Math.floor(3.4) = 3 + * -> ones[3] = 5 // this is wrong + * -> 3 - 2 = 1 -> ones[1] = 6 + * + * To find ones part, unit is identified by n % 10 + * If > 0 then ones word is appended to tens word otherwise nothing + * e.g., + * 1. 34 -> 10 + * 2. 30 -> 6 + */ + if (n >= 20 && n < 100) { + const unit = n % 10 + return tens[Math.floor(n / 10 - 2)] + ((unit !== 0) ? ones[unit] : 0) + } + + // Find thousand, hundred and sub part + const hundred = Math.floor(n / 100) % 10 + const thousand = Math.floor(n / 1000) + const sub = n % 100 + + // Find ones for thousand part number + // e.g., thousand = 2 => inWord = twothousand + if (n > 999) { + count += numberToWordLength(thousand) + thousandLength + } + + // Find ones for hundred part number + // e.g., hundred = 1 => inWord = onehundred + if (hundred !== 0) { + count += ones[hundred] + hundredLength + } + + // Find and part of number + // e.g., 922 => ninehundred"andtwentytwo" + if (sub !== 0) { + count += andLength + numberToWordLength(sub) + } + + // return number in word format + return count +} + +/** + * Function responsible for calculating total number word length + * for provided input number + * Validation is performed for input + * Loop is executed to find total word length for given number range + * starting from 1 + * + * + * @param {number} number + * @returns {number} + */ +const countNumberWordLength = (number) => { + let count = 0 + + // Not a number check + if (Number.isNaN(parseInt(number))) { + throw new Error('Invalid input, please provide valid number') + } + + // Number should be greater than 1 + if (number < 1) { + throw new Error('Please provide number greater that 1') + } + + // Loop to calculate word length by calling {@link numberToWord} + for (let i = 1; i <= number; i++) { + count += numberToWordLength(i) + } + + // return final count for number word length + return count +} + +export { countNumberWordLength } diff --git a/Project-Euler/test/Problem017.test.js b/Project-Euler/test/Problem017.test.js new file mode 100644 index 0000000000..3688d7bb60 --- /dev/null +++ b/Project-Euler/test/Problem017.test.js @@ -0,0 +1,14 @@ +import { countNumberWordLength } from '../Problem017.js' + +describe('Number letter count', () => { + test.each([[5, 19], [100, 864], [1000, 21124]])('Number letter count from 1 to %i', (n, expected) => { + expect(countNumberWordLength(n)).toBe(expected) + }) + + test.each([ + ['test', 'Invalid input, please provide valid number'], + [0, 'Please provide number greater that 1'] + ])('Should throw an error for input %i', (n, expected) => { + expect(() => countNumberWordLength(n)).toThrowError(expected) + }) +}) pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy