diff --git a/src/index.js b/src/index.js index e8b98a08..114bc8c5 100644 --- a/src/index.js +++ b/src/index.js @@ -85,6 +85,7 @@ import first from './first' import mode from './mode-array' import rollDice from './rollDice' import inchesToMetric from './inches-to-metric' +import numberToString from './numberToString' export { reverseArrayInPlace, @@ -174,4 +175,5 @@ export { mode, rollDice, inchesToMetric, + numberToString, } diff --git a/src/numberToString.js b/src/numberToString.js new file mode 100644 index 00000000..cd1caa3a --- /dev/null +++ b/src/numberToString.js @@ -0,0 +1,69 @@ +/*eslint complexity: ["error", 10]*/ +export default numberToString + +/** + * Original source: https://stackoverflow.com/questions/5529934/javascript-numbers-to-words + * + * Converts an int to its string representation + * + * @param {Number} number - input integer (MAX_SAFE_INTEGER) + * @return {String} - String representation of the integer + */ + +const stringLookup = [ + {key: 1000000000000000, value: 'quadrillion'}, + {key: 1000000000000, value: 'trillion'}, + {key: 1000000000, value: 'billion'}, + {key: 1000000, value: 'million'}, + {key: 1000, value: 'thousand'}, + {key: 100, value: 'hundred'}, + {key: 90, value: 'ninety'}, + {key: 80, value: 'eighty'}, + {key: 70, value: 'seventy'}, + {key: 60, value: 'sixty'}, + {key: 50, value: 'fifty'}, + {key: 40, value: 'forty'}, + {key: 30, value: 'thirty'}, + {key: 20, value: 'twenty'}, + {key: 19, value: 'nineteen'}, + {key: 18, value: 'eighteen'}, + {key: 17, value: 'seventeen'}, + {key: 16, value: 'sixteen'}, + {key: 15, value: 'fifteen'}, + {key: 14, value: 'fourteen'}, + {key: 13, value: 'thirteen'}, + {key: 12, value: 'twelve'}, + {key: 11, value: 'eleven'}, + {key: 10, value: 'ten'}, + {key: 9, value: 'nine'}, + {key: 8, value: 'eight'}, + {key: 7, value: 'seven'}, + {key: 6, value: 'six'}, + {key: 5, value: 'five'}, + {key: 4, value: 'four'}, + {key: 3, value: 'three'}, + {key: 2, value: 'two'}, + {key: 1, value: 'one'}, +] + +function numberToString(number) { + if (number <= 0 || number > Number.MAX_SAFE_INTEGER) { + return 'Number needs to be grater than 0 or less than 2^53-1.' + } + let result = '' + + for (const n of stringLookup) { + if (number >= n.key) { + if (number < 100) { + result += n.value + number -= n.key + number > 0 ? result += ' ' : result + } else { + const t = Math.floor(number / n.key) + const d = number % n.key + return d > 0 ? `${numberToString(t)} ${n.value} ${numberToString(d)}` : `${numberToString(t)} ${n.value}` + } + } + } + return result +} diff --git a/test/numberToString.test.js b/test/numberToString.test.js new file mode 100644 index 00000000..2c3787a6 --- /dev/null +++ b/test/numberToString.test.js @@ -0,0 +1,35 @@ +import test from 'ava' +import {numberToString} from '../src' + +test('Convert lowest allowed number to string', t => { + const number = 1 + const stringNum = 'one' + const actual = numberToString(number) + t.deepEqual(actual, stringNum) +}) + +test('Convert high number like 214124124 to string', t => { + const number = 214124124 + const stringNum = `two hundred fourteen million one hundred twenty four thousand one hundred twenty four` + const actual = numberToString(number) + t.deepEqual(actual, stringNum) +}) + +test('Convert 1000 to string', t => { + const number = 1000 + const stringNum = `one thousand` + const actual = numberToString(number) + t.deepEqual(actual, stringNum) +}) + +test('Zero and negative numbers should return error message', t => { + const actual = numberToString(0) + const errorMessage = 'Number needs to be grater than 0 or less than 2^53-1.' + t.deepEqual(actual, errorMessage) +}) + +test('Numbers greater than Number.MAX_SAFE_INTEGER should return error message', t => { + const actual = numberToString(Number.MAX_SAFE_INTEGER + 1) + const errorMessage = 'Number needs to be grater than 0 or less than 2^53-1.' + t.deepEqual(actual, errorMessage) +}) \ No newline at end of file