forked from TheAlgorithms/JavaScript
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Problem017.js
117 lines (100 loc) · 3.18 KB
/
Problem017.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
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 }