Skip to content

Instantly share code, notes, and snippets.

@tremby
Last active May 6, 2019 20:13
Show Gist options
  • Save tremby/72e9845032aba23dfb396995fad1c5da to your computer and use it in GitHub Desktop.
Save tremby/72e9845032aba23dfb396995fad1c5da to your computer and use it in GitHub Desktop.
Integer to words coding challenge
UNIT_WORD = [
'zero',
'one',
'two',
'three',
'four',
'five',
'six',
'seven',
'eight',
'nine',
];
TENS_WORD = [
'',
'ten',
'twenty',
'thirty',
'fourty',
'fifty',
'sixty',
'seventy',
'eighty',
'ninety',
];
TEENS_WORD = [
'ten',
'eleven',
'twelve',
'thirteen',
'fourteen',
'fifteen',
'sixteen',
'seventeen',
'eighteen',
'nineteen',
];
MULT_WORD = [
'',
'thousand',
'million',
'billion',
'trillion',
];
function words(number) {
const numberString = number.toString();
if (!/^([1-9]\d*|0)$/.test(numberString)) {
throw new Error("Input must be a non-negative integer with no leading zeroes");
}
if (numberString.length > MULT_WORD.length * 3) {
throw new Error("Can't handle numbers this big");
}
// Split into array of integer digits
const digits = numberString.split('').map(s => parseInt(s, 10));
// Short-circuit for single digit (also the only way to output "zero")
if (digits.length === 1) {
return UNIT_WORD[digits[0]];
}
// Split into chunks of three, from end to start
const triples = [];
while (digits.length >= 3) {
triples.unshift(digits.splice(-3, 3));
}
if (digits.length) {
// Pad leftovers with zeros
while (digits.length < 3) {
digits.unshift(0);
}
triples.unshift(digits);
}
// Turn it into words
let output = '';
for (const [triple, [h, t, u]] of Object.entries(triples)) {
let words = '';
let comma = true;
if (h) {
words = `${UNIT_WORD[h]} hundred`;
}
if (h && (t || u)) {
words += " and ";
}
if (t === 1 && u) {
words += TEENS_WORD[u];
} else if (t) {
words += TENS_WORD[t];
if (u) {
words += "-";
}
}
if (t !== 1 && u) {
words += UNIT_WORD[u];
}
if (h || t || u) {
const mult = triples.length - triple - 1;
if (mult > 0) {
words += " " + MULT_WORD[mult];
} else if (!h) {
comma = false;
}
}
if (words.length) {
if (output.length) {
if (comma) {
output += ', ';
} else {
output += ' and ';
}
}
output += words;
}
}
return output;
}
function test(input) {
console.log(`Input: ${input}, output: ${words(input)}`);
}
for (let i = 0; i < 20; i++) {
test(i);
}
for (i of [
20,
25,
99,
100,
105,
120,
123,
200,
333,
1000,
1001,
1010,
1011,
1100,
1101,
1110,
1111,
1234,
12345,
123456,
1234567,
12345678,
123456789,
1234567890,
12345678901,
123456789012,
1234567890123,
12345678901234,
123456789012345,
300000000000000,
300000000000001,
999999999999999,
]) {
test(i);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment