I read this question Figure/number to text converter javascript implementation. Like the answer said, that version has two main issues. I tried to solve them.
The main issues with the original:
The assumption you can switch language by just providing the words for the main numbers is not correct, since numbers are built differently in different languages.
My solution: I have one function per language and some global helper functions.
It uses too many design patterns, especially fluent APIs.
My solution: It consists of function calls with an inner helper function for the hundreds and some outer helper functions.
Please give ome feedback on the programming itself. You don't have necessarily have to correct my Dutch ;-)
Note: I only support positive integers. It's a linguistic question, but if someone knows: 2.24
can be pronounced as twee komma vierentwintig (two point twenty four)
, but how do you pronounce decimal fractions starting with zero like 2.024
. Is it twee komma nul vierentwintig (two point zero twenty four)
or twee komma nul twee vier (two point zero two four)
?
function transcribe_nl(number) {
let NUMBER_0 = 'nul'
let NUMBER_10 = 'tien'
let NUMBERS_FROM_0_TO_19 = [NUMBER_0, 'een', 'twee', 'drie', 'vier', 'vijf', 'zes', 'zeven', 'acht', 'negen', NUMBER_10, 'elf', 'twaalf', 'dertien', 'veertien', 'vijftien', 'zestien', 'zeventien', 'achttien', 'negentien']
let MULTITUDES_OF_10 = [undefined, NUMBER_10, 'twintig', 'dertig', 'veertig', 'vijftig', 'zestig', 'zeventig', 'tachtig', 'negentig']
let NUMBER_100 = 'honderd'
let NUMBER_1000 = 'duizend'
let POWERS_OF_1000 = [undefined, NUMBER_1000, 'miljoen', 'miljard', 'biljoen', 'biljard', 'triljoen', 'triljard', 'quadriljoen', 'quadriljard', 'quintiljoen', 'quintiljard']
if (number === 0) {
return NUMBER_0
}
let text_full = []
let _3_digit_group_numbers = [...split_in_digit_groups(number, 3)]
for (let power_of_1000 = _3_digit_group_numbers.length - 1; power_of_1000 >= 0; --power_of_1000) {
let number_3_digit_group = _3_digit_group_numbers[power_of_1000]
// translate 3 digit group
let text_3_digit_group = transcribe_xxx(number_3_digit_group)
if (text_3_digit_group === undefined) continue
let text_power_of_1000 = POWERS_OF_1000[power_of_1000]
let text_xxx_power_of_1000
if (power_of_1000 === 0) {
text_xxx_power_of_1000 = text_3_digit_group
} else if (power_of_1000 === 1) {
if (number_3_digit_group === 1) {
text_xxx_power_of_1000 = NUMBER_1000
} else {
text_xxx_power_of_1000 = text_3_digit_group + text_power_of_1000
}
} else {
text_xxx_power_of_1000 = text_3_digit_group + ' ' + text_power_of_1000
}
text_full.push(text_xxx_power_of_1000)
}
return text_full.join(' ')
function transcribe_xxx(number_xxx) {
let [digit_x, digit_x0, digit_x00] = split_in_digits(number_xxx)
// assemble 00-99
let text_xx
let number_xx = number_xxx % 100
if (number_xx === 0) {
text_xx = undefined
} else if (digit_x === 0) { // pure multiple of 10
text_xx = MULTITUDES_OF_10[digit_x0]
} else if (number_xx < 20) { // between 11 and 19
text_xx = NUMBERS_FROM_0_TO_19[number_xx]
} else { // non-pure multiple of 10 between 21 and 99
let text_x = NUMBERS_FROM_0_TO_19[digit_x]
let text_x0 = MULTITUDES_OF_10[digit_x0]
let last_letter_x_1 = text_x[text_x.length - 1]
let text_and = (/[aeiou]/gi).test(last_letter_x_1) ? 'ën' : 'en'
text_xx = text_x + text_and + text_x0 // e.g. eenentwintig, tweeëntwintig
}
// assemble hundreds
let text_x00
if (number_xxx < 100) {
text_x00 = undefined
} else if (digit_x00 === 1) {
text_x00 = NUMBER_100
} else {
text_x00 = NUMBERS_FROM_0_TO_19[digit_x00] + NUMBER_100
}
// combine 00-99 and hundreds
let text_xxx
if (text_x00 === undefined) {
text_xxx = text_xx
} else if (text_xx === undefined) {
text_xxx = text_xxx
} else if (number_xx <= 12) {
text_xxx = text_x00 + 'en' + text_xx
} else {
text_xxx = text_x00 + text_xx
}
return text_xxx
}
}
function get_max_power_of_1000(number) {
return Math.floor(Math.log10(number) / 3)
}
function slice_number(number, index, end_index) {
let size = end_index - index
if (number < 10 ** index) return undefined
return Math.floor(number / 10 ** index % (10 ** size))
}
function * split_in_digits(number) {
yield * split_in_digit_groups(number, 1)
}
function * split_in_digit_groups(number, group_size) {
while (true) {
let unit = number % (10 ** group_size)
yield unit
number = (number - unit) / (10 ** group_size)
if (number == 0) break
}
}
function transcribe_en(number) {
}
let languages = {
nl: transcribe_nl,
en: transcribe_en,
}
/**
* @param {number} number
* @param {string} language
*/
function transcribe(number, language) {
if (languages[language]) {
languages[language](number);
} else {
throw new Error("Language not supported" + language);
}
}
console.log(transcribe_nl(9876543210))