DEV Community

German Cyganov
German Cyganov

Posted on • Originally published at Medium

Teaching the computers to write number names using JavaScript

Today we will try to teach the computer to translate numbers into words

First Step

Let's use the number-word dictionary

const numberWords = {
  0: 'zero',
  1: 'one',
  2: 'two',
  3: 'three',
  4: 'four',
  5: 'five',
  6: 'six',
  7: 'seven',
  8: 'eight',
  9: 'nine',
  10: 'ten',
}
Enter fullscreen mode Exit fullscreen mode

And then?

Let's write a function that will return a value if there is one in the dictionary, and false if no word for the number is given

function getNumberWord(number) {
  if (numberWords.hasOwnProperty(number)) {
    return numberWords[number]
  } else {
    return false
  }
}
Enter fullscreen mode Exit fullscreen mode

Let's write the code to output the results of our work

const number = process.argv[2]
console.log(getNumberWord(number))
Enter fullscreen mode Exit fullscreen mode

First result

node index.js 5
five
Enter fullscreen mode Exit fullscreen mode

Great!

Moving forward

node index.js 101
false
Enter fullscreen mode Exit fullscreen mode

Not bad

We learned how to convert simple numbers into words, but what if we want to work with numbers that are not in our dictionary? Possibly we could identify all the numbers in the dictionary. But

  • This is boring
  • And memory consuming

Learning to make words

So that you don't have to spend all day compiling dictionaries and leave your computer with a little more memory for more important tasks. And it has them, believe me!

Modify our program so that it adds the result of digit translation to the resulting string

const number = process.argv[2]

let result = ''
number.forEach((digit) => {
  result += getNumberWord(digit)
})

console.log(result)
Enter fullscreen mode Exit fullscreen mode
node index.js 101
onezeroone
Enter fullscreen mode Exit fullscreen mode

Good!

Add power

Define a dictionary for the powers, the key of which will be the number of zeros in the number

const numberZeros = {
  1: 'ten',
  2: 'hundred',
  3: 'thousand',
  6: 'million',
}
Enter fullscreen mode Exit fullscreen mode

By analogy with the function of getting the number word value, let's write the function of getting the word for the power

function getPowerWord(power) {
  if (numberZeros.hasOwnProperty(power)) {
    return numberZeros[power]
  } else {
    return false
  }
}
Enter fullscreen mode Exit fullscreen mode

Change the program so that it adds a power of a number

const number = process.argv[2]

let result = ''

const power = number.length - 1
const numberPowerWord = getPowerWord(power)
result += numberPowerWord + getNumberWord(number.substr(power))

console.log(result)
Enter fullscreen mode Exit fullscreen mode
node index.js 101
hundredone
Enter fullscreen mode Exit fullscreen mode

But the current solution has problems, firstly it stopped working with the our previous number, and secondly it knows how to work with only one power

Try this solution with a number whose power is not defined in the dictionary

node index.js 10000001
false1
Enter fullscreen mode Exit fullscreen mode

Any problem?

Putting words together

To convert the power of a number, divide the number into two by adding the name of the digit between them. Also remember to check for power numbers such as "ten" in the dictionary, and use them instead of further dividing the number

example

function convertPoweredNumber(number) {
  let firstDigits = ''

  for (let i = 0; i < number.length; i++) {
    firstDigits += number[i]

    const power = number.length - firstDigits.length
    const powerWord = getPowerWord(power)

    if (powerWord) {
      const nextDigitPos = firstDigits.length
      const numberWord = getNumberWord(firstDigits[0] + Array(power).fill('0').join(''))

      return numberWord
        ? numberWord + convert(number.substr(nextDigitPos))
        : convert(firstDigits) + powerWord + convert(number.substr(nextDigitPos))
    }
  }

  return ''
}
Enter fullscreen mode Exit fullscreen mode

In the second number we can get extra zeros in the beginning. Let's split the number 10001 without having a thousand power in the dictionary, we get 100 and 01, on the next iteration we will not find 01 in the number dictionary, and again send it for splitting for powers. As a result, instead of the correct output "one" we will get "tenone"

Moreover, the user can enter a number starting with zero himself

To avoid such situations, we will delete the leading zeros in the number

function removeLeadingZeros(number) {
  return number.replace(/^0+/, '')
}
Enter fullscreen mode Exit fullscreen mode

Let's return the former functionality of the program and add the ability to work with power

function convert(number) {
  const numberWithoutZeros = removeLeadingZeros(number)
  return getNumberWord(numberWithoutZeros) || convertPoweredNumber(numberWithoutZeros)
}
Enter fullscreen mode Exit fullscreen mode
const number = process.argv[2]
console.log(convert(number))
Enter fullscreen mode Exit fullscreen mode
node index.js 101
onehundredone
Enter fullscreen mode Exit fullscreen mode

Finish!

node index.js 1000000047
onethousandmillionfourtenseven
Enter fullscreen mode Exit fullscreen mode

To separate words, let's add a space to the values in the dictionaries, at the same time adding the value of "forty" to the dictionary of numbers

node index.js 1000000047
one thousand million forty seven
Enter fullscreen mode Exit fullscreen mode

Complete code can be found on GitHub

Top comments (0)