Facebook Interview Question
Web DevelopersCountry: United States
Interview Type: Phone Interview
Here's my solution in C#.NET. I haven't been able to break it yet. It handles values up to 999 trillion, easy to extend, relatively easy to read, fast
public class WholeNumberParser
{
private Stack<long> intermediateAddends = new Stack<long>();
private Stack<long> intermediateNumbers = new Stack<long>();
private Dictionary<string, long> numbers = new Dictionary<string, long>()
{
{ "one", 1 },
{ "two", 2 },
{ "three", 3 },
{ "four", 4 },
{ "five", 5 },
{ "six", 6 },
{ "seven", 7 },
{ "eight", 8 },
{ "nine", 9 },
{"ten", 10 },
{"eleven", 11 },
{"twelve", 12 },
{"thirteen", 13 },
{"fourteen", 14 },
{"fifteen", 15 },
{"sixteen", 16 },
{"seventeen", 17 },
{"eighteen", 18 },
{"nineteen", 19 },
};
private Dictionary<string, long> addends = new Dictionary<string, long>
{
{"twenty", 20 },
{"thirty", 30 },
{"fourty", 40 },
{"fifty", 50 },
{"sixty", 60 },
{"seventy", 70 },
{"eighty", 80 },
{"ninety", 90 },
};
private Dictionary<string, long> factors = new Dictionary<string, long>()
{
{"hundred", 100 },
{"thousand", 1000 },
{"million", 1000000 },
{"billion", 1000000000 },
{"trillion", 1000000000000 },
};
private Regex ignored = new Regex("and", RegexOptions.IgnoreCase | RegexOptions.Multiline);
public long? Parse(string numberExpression)
{
bool success = false;
var tokens = numberExpression.Split(' ');
for (var i = 0; i < tokens.Length; ++i)
{
var token = tokens[i];
if(ignored.IsMatch(token)) continue;
success = PushValues(token);
if (success == false) break;
}
return success ? TotalValues() : null;
}
private bool PushValues(string token)
{
bool success = false;
long addend;
success = GetAddend(token, out addend);
if (success)
{
if (intermediateNumbers.Any())
{
addend += intermediateNumbers.Pop();
}
intermediateAddends.Push(addend);
return true;
}
long number;
success = GetNumber(token, out number);
if (success)
{
if (intermediateAddends.Any())
{
var intermediateAddend = intermediateAddends.Pop();
number += intermediateAddend;
}
intermediateNumbers.Push(number);
return true;
}
long factor;
success = GetFactor(token, out factor);
if (success)
{
if (intermediateNumbers.Any())
{
var intermediateNumber = intermediateNumbers.Pop();
factor *= intermediateNumber;
}
intermediateNumbers.Push(factor);
return true;
}
return false;
}
private bool GetAddend(string numberExpression, out long addend)
{
return addends.TryGetValue(numberExpression, out addend);
}
private bool GetNumber(string numberExpression, out long number)
{
return numbers.TryGetValue(numberExpression, out number);
}
private bool GetFactor(string numberExpression, out long number)
{
return factors.TryGetValue(numberExpression, out number);
}
private long? TotalValues()
{
return intermediateNumbers.Aggregate((total, value) => total += value);
}
}
Also tried it in C# and came up with the following. Much simpler and works for any number as well, unless I'm missing something.
public class Solution
{
public SortedDictionary<int, string> words = new SortedDictionary<int, string>
(Comparer<int>.Create((a,b)=> b-a))
{
{1000*1000,"million" },
{1000,"thousand" },
{100, "hundred" },
{90, "ninety" },
{80, "eighty" },
{70, "seventy" },
{60, "sixty" },
{50, "fifty" },
{40, "fourty" },
{30, "thirty" },
{20, "twenty" },
{19, "nineteen" },
{18, "eigteen" },
{17, "seventeen" },
{16, "sixteen" },
{15, "fifteen" },
{14, "fourteen" },
{13, "thirteen" },
{12, "twelve" },
{ 11, "eleven" },
{ 10, "ten" },
{ 9, "nine" },
{ 8, "eight" },
{ 7, "seven" },
{ 6, "six" },
{ 5, "five" },
{ 4, "four" },
{ 3, "three" },
{ 2, "two" },
{ 1, "one" }
};
public string ToSentence(int integer)
{
var sentence = "";
int amountleft = integer;
foreach (var kv in words)
{
int amount = amountleft / kv.Key;
if (amount > 1 || amount == 1 && kv.Key > 99)
{
sentence += $" {ToSentence(amount)} {kv.Value}";
amountleft -= kv.Key * amount;
}
else if (amount == 1)
{
sentence += $" {kv.Value}";
amountleft -= kv.Key * amount;
}
}
return sentence;
}
}
public class IntToString {
static Map<Integer,String> digit2Text = new HashMap<>();
static Map<Integer, String> decimalDigits = new HashMap<>();
static{
digit2Text.put(1,"one");
digit2Text.put(2,"two");
digit2Text.put(3,"three");
digit2Text.put(4,"four");
digit2Text.put(5,"five");
digit2Text.put(6,"six");
digit2Text.put(7,"seven");
digit2Text.put(8,"eight");
digit2Text.put(9,"nine");
digit2Text.put(10,"ten");
digit2Text.put(11,"eleven");
digit2Text.put(12,"twelve");
digit2Text.put(13,"thirteen");
digit2Text.put(14,"fourteen");
digit2Text.put(15,"fifteen");
digit2Text.put(16,"sixteen");
digit2Text.put(17,"seventeen");
digit2Text.put(18,"eighteen");
digit2Text.put(19,"nineteen");
decimalDigits.put(2, "twenty");
decimalDigits.put(3, "thirty");
decimalDigits.put(4, "fourty");
decimalDigits.put(5, "fifty");
decimalDigits.put(6, "sixty");
decimalDigits.put(7, "seventy");
decimalDigits.put(8, "eighty");
decimalDigits.put(9, "ninety");
}
public static void main(String[] args){
System.out.println("55: " + IntToString.getCurrNumStr(55));
System.out.println("305: " + IntToString.getCurrNumStr(305));
System.out.println("52168: " + IntToString.int2Str(52168));
System.out.println("1234567890: " + IntToString.int2Str(1234567890));
}
public static Queue<String> getOrder(){
Queue<String> order = new LinkedList<>();
order.add("");
order.add("thousand");
order.add("million");
order.add("billion");
order.add("trillion");
return order;
}
public static String int2Str(int num){
String retVal = "";
Queue<String> order = getOrder();
while(num > 0) {
String currOrder = order.poll();
int currNum = num % 1000;
num = num / 1000;
retVal = getCurrNumStr(currNum) + " " + currOrder + " "+ retVal;
}
return retVal;
}
public static String getCurrNumStr(int num){
String retVal = "";
int hundreds = num / 100;
int belowHundreed = num % 100;
if(belowHundreed < 20){
retVal = digit2Text.get(belowHundreed);
} else {
int digit = belowHundreed % 10;
int decimalDigit = belowHundreed / 10;
if (digit != 0) {
retVal = digit2Text.get(digit);
if (decimalDigit != 0) {
retVal = decimalDigits.get(decimalDigit) + " " + retVal;
}
} else {
if (decimalDigit != 0) {
retVal = decimalDigits.get(decimalDigit) + " " + retVal;
}
}
}
if(hundreds != 0){
String hundredsStr = digit2Text.get(hundreds);
hundredsStr = hundredsStr + " hundreed";
if(retVal.length() > 0){
retVal = hundredsStr + " and " + retVal;
} else {
retVal = hundredsStr;
}
}
return retVal;
}
}
This is my take on the question
case num ==0 output Zero
case num != 0
split it in 1000s (0-999) append thousand, million or billion appropriately
split it in 100s (0-99)
case 0-19 append the word from n0to19
case 20-99 append tens place from n10s and ones place from n0to19
split hundreds place append word from n0to19 and hundred if not empty
Note : need to append "and" if number is less than 1000 and has tens and ones place
public class Num2W
{
static String[] n0to19 = {"", " One", " Two", " Three",
" Four", " Five", " Six", " Seven",
" Eight", " Nine", " Ten", " Eleven",
" Twelve", " Thirteen", " Fourteen", " Fifteen",
" Sixteen", " Seventeen", " Eighteen", " Nineteen"};
static String[] n10s = {" Twenty", " Thirty", " Fourty", " Fifty",
" Sixty", " Seventy", " Eighty", " Ninety"};
static String[] nmulk = {"", " Thousand,", " Million,", " Billion,"};
private static String convert(int n, int sfix)
{
String inW = "";
if (n != 0) {
int tmp = n % 100;
if (tmp != 0) {
if (tmp < 20)
inW = n0to19[tmp];
else
inW = n10s[(tmp / 10) - 2] + n0to19[tmp % 10];
if (sfix == 0)
inW = " and" + inW;
}
tmp = n / 100;
if (tmp != 0)
inW = n0to19[tmp] + " Hundred" + inW;
inW += nmulk[sfix];
}
return inW;
}
public static void main(String[] args)
{
int n = (new Scanner(System.in)).nextInt();
String out = "";
if (n == 0)
out = " Zero";
else
for (int i = 0; n != 0; i++) {
out = convert(n % 1000, i) + out;
n /= 1000;
}
System.out.println("In Words :" + out);
}
}
const _trillion = 1000000000000;
const _billion = 1000000000;
const _million = 1000000;
const _thousand = 1000;
const _hundred = 100;
function describe_less_than_ten( n ) {
if( n==9 )
return "nine";
if( n==8 )
return "eight";
if( n==7 )
return "seven";
if( n==6 )
return "six";
if( n==5 )
return "five";
if( n==4 )
return "four";
if( n==3 )
return "three";
if( n==2 )
return "two";
if( n==1 )
return "one";
return "zero"
}
function describe_less_than_hundred( n ) {
// TODO: generate: these numbers by describe_less_than_ten()+"ty"???
if( n>=90 )
return "ninety" +((n%10)?" "+describe_less_than_ten(n%10):"");
if( n>=80 )
return "eighty" +((n%10)?" "+describe_less_than_ten(n%10):"");
if( n>=70 )
return "seventy"+((n%10)?" "+describe_less_than_ten(n%10):"");
if( n>=60 )
return "sixty" +((n%10)?" "+describe_less_than_ten(n%10):"");
if( n>=50 )
return "fifty" +((n%10)?" "+describe_less_than_ten(n%10):"");
if( n>=40 )
return "fourty" +((n%10)?" "+describe_less_than_ten(n%10):"");
if( n>=30 )
return "thirty" +((n%10)?" "+describe_less_than_ten(n%10):"");
if( n>=20 )
return "twenty" +((n%10)?" "+describe_less_than_ten(n%10):"");
// TODO: generate *teen numbers by describe_less_than_ten()+"teen"???
if( n==19 )
return "nineteen";
if( n==18 )
return "eighteen";
if( n==17 )
return "seventeen";
if( n==16 )
return "sixteen";
if( n==15 )
return "fifteen";
if( n==14 )
return "fourteen";
if( n==13 )
return "thirteen";
if( n==12 )
return "twelve";
if( n==11 )
return "eleven";
if( n==10 )
return "ten";
return describe_less_than_ten(n);
}
function describe_less_than_thousand( n ) {
if( n<_hundred )
return describe_less_than_hundred(n);
return describe_less_than_ten(Math.floor(n/_hundred))+" hundred "+describe_less_than_hundred(n%_hundred);
}
function smart_join( trillions, billions, millions, thousands, hundreds, therest ) {
let result = [];
if( trillions>0 )
result.push(describe_less_than_thousand(trillions)+" trillion");
if( billions>0 )
result.push(describe_less_than_thousand(billions)+" billion");
if( millions>0 )
result.push(describe_less_than_thousand(millions)+" million");
if( thousands>0 )
result.push(describe_less_than_thousand(thousands)+" thousand");
if( hundreds>0 )
result.push(describe_less_than_hundred(hundreds)+" hundred");
if( therest>0 )
result.push(describe_less_than_hundred(therest));
if( result.length==0 )
result.push("zero");
return result.join(" ");
}
function describe_number( n ) {
if( n<0 )
return "negative "+describe_number(-n);
return smart_join(
Math.floor( n/_trillion ),
Math.floor( (n%_trillion)/_billion ),
Math.floor( (n%_billion)/_million ),
Math.floor( (n%_million)/_thousand ),
Math.floor( (n%_thousand)/_hundred ),
(n%_hundred));
}
console.log(describe_number(Number(process.argv[2])));
Hi there,
in this solution I'm taking advatange of generating words for three digits. When you look at any number you can see that mainly you generate words up till hundrets and after that you just add specific word if needed eg. thousand, milion etc. My solution can be easliy extended, by just adding new values into array like billion etc.
{
static string[] singleArray = new string[]{"", "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten",
"Eleven", "Twelve", "Thirteen", "Fourteen", "Fifteen", "Sixteen", "Seventeen", "Eighteen", "Nineteen"};
static string[] dozensArray = new string[]{"","Ten","Twenty","Thirty","Fourty", "Fifty", "Sixty", "Seventy", "Eighty", "Ninety"};
static string hundretLiteral = "Hundret";
static string[] higherOrdersArray = new string[]{"","Thousand","Milion"};//etc.
static int Main(string[] args){
int number = 5113257;
string stringToAppend= String.Empty;
StringBuilder result = new StringBuilder();
int i=0;
while(number!=0 && i<higherOrdersArray.Length){
ThreeDigitsToString(result, ref number, i);
i++;
}
Console.WriteLine(result.ToString());
return 0;
}
private static void ThreeDigitsToString(StringBuilder result, ref int number, int counter)
{
//Dozens to string
int modNumber = number % 100;
string outputString = String.Empty;
if(modNumber<20 && modNumber>0){
outputString = singleArray[modNumber]+" ";
}else{
outputString=dozensArray[(number/10)%10]+" "+singleArray[number%10]+" ";
}
int dividedNumber = number/100;
modNumber=dividedNumber%10;
//hundrets to string
if(modNumber>0){
outputString = singleArray[modNumber]+" "+hundretLiteral+(counter>0?" ":" and ") + outputString;
}
//higher order endings
if(counter>0){
outputString = outputString+ higherOrdersArray[counter]+", ";
}
number = dividedNumber/10;
result.Insert(0,outputString);
}
}
A code to support from 1 to 9999
public class ConvertInteger2EnglishPhrase {
public static void main(String[] args) {
String[] ones = {"", "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine"};
String[] teens = {"", "Eleven", "Twelve", "Thirteen", "Fourteen", "Fifteen", "Sixteen", "Seventeen", "Eighteen", "Ninteen"};
String[] tens = {"", "Ten", "Twenty", "Thirty", "Fourty", "Fifty", "Sixty", "Seventy", "Eighty", "Ninty"};
String[] hundreds = new String[10];
for (int i = 0; i < 10; i++) {
hundreds[i] = ones[i] + " " + "Hundred";
}
String[] thousands = new String[10];
for (int i = 0; i < 10; i++) {
thousands[i] = ones[i] + " " + "Thousand";
}
String[][] numbers = {ones, tens, hundreds, thousands};
int input = 117;
String out = "";
int len;
int divider = 1;
for (int j = 1; j <= 9999; j++) {
input = j;
out = "";
while (input > 0) {
if (input > 0 && input < 10) {
out += " " + ones[input % 10];
break;
} else if (input > 10 && input < 20) {
out += " " + teens[input % 10];
break;
} else {
// get # of digit
len = String.valueOf(input).length();
divider = 1;
for (int i = 0; i < (len - 1); i++)
divider *= 10;
int quotient = input / divider;
out += " " + numbers[len - 1][quotient];
input -= divider * quotient;
}
}
System.out.println(out);
}
}
}
Very easily extendable code/
// C++ program to find count of endless points
#include<bits/stdc++.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
using namespace std;
const int MAX = 100;
/* The first string is not used, it is to make
array indexing simple */
string single_digits[10] = { "", "one", "two",
"three", "four","five",
"six", "seven", "eight", "nine"};
/* The first string is not used, it is to make
array indexing simple */
string two_digits[11] = {"", "ten", "eleven", "twelve",
"thirteen", "fourteen",
"fifteen", "sixteen",
"seventeen", "eighteen", "nineteen"};
/* The first two string are not used, they are to make
array indexing simple*/
string tens_multiple[10] = {"", "", "twenty", "thirty", "forty", "fifty",
"sixty", "seventy", "eighty", "ninety"};
string hundred= "hundred";
string power3[] = {"", "thousand", "million"};
string printlessThanThousand(int i) {
string output;
if (i >100) {
output += single_digits[i/100];
output += " ";
output += hundred;
i = i%100;
}
if (i>9 && i < 20) {
output += " ";
output += two_digits[i-9];
return output;
}
if (i>19) {
output += " ";
output += tens_multiple[i/10];
i = i%10;
}
output += " ";
output += single_digits[i];
return output;
}
void convert_to_words(int i)
{
std::string words = std::to_string(i);
/* Base cases */
if (words.size() == 0) {
fprintf(stderr, "empty string\n");
return;
}
if (words.size() > 7) {
fprintf(stderr, "Length more than 7 is not supported\n");
return;
}
if (i == 0) cout << "Zero" << endl;
int allowed = sizeof power3/sizeof power3[0];
string output;
for (int x=allowed; x >= 0; --x) {
int p = pow(1000, x);
if (i/p > 0) {
output += printlessThanThousand(int(i/p));
output += " ";
output += power3[x];
output += " ";
i %= p;
}
}
cout << output << endl;
}
/* Driver program to test above function */
int main(void)
{
convert_to_words(9923);
convert_to_words(523);
convert_to_words(89);
convert_to_words(8989);
convert_to_words(8123989);
return 0;
}
public String announce(int value) {
String total_number = "";
String number[] = {"", "one", "two", "three", "four", "five", "six", "seven","eight", "nine", "ten"};
String tens[] = {"", "ten", "twenty", "thirty", "forty", "fifty", "sixty","seventy", "eighty", "ninety"};
String teens[] = {"", "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen","seventeen", "eighteen", "nineteen"};
String thousands[] = {"", "thousand", "million", "billion", "trillion"};
int count = 0;
Stack<Integer> stack = new Stack<>();
int tempVal = value;
while (tempVal/1000 > 0) {
stack.push(tempVal % 1000);
count ++;
tempVal /= 1000;
}
do {
if (!total_number.isEmpty()) {
total_number+= " and ";
}
boolean added = false;
if (tempVal /100 > 0) {
total_number += number[tempVal/100]+" hundred ";
added = true;
}
tempVal %= 100;
if (tempVal > 0) {
if (added)
total_number += "and ";
if (tempVal < 11) {
total_number+= number[tempVal];
} else if (tempVal %10 == 0) {
total_number+= tens[tempVal/10];
} else if (tempVal/10 == 1) {
total_number += teens[tempVal %10];
} else {
total_number += tens[tempVal/10] + " "+ number[tempVal%10];
}
}
if (count > 0) {
if (tempVal > 0)
total_number += " " + thousands[count];
count --;
if (!stack.isEmpty())
tempVal = stack.pop();
else
tempVal = -1;
} else
tempVal = -1;
} while(tempVal != -1);
return total_number;
}
public String announce(int value) {
String total_number = "";
String number[] = {"", "one", "two", "three", "four", "five", "six", "seven","eight", "nine", "ten"};
String tens[] = {"", "ten", "twenty", "thirty", "forty", "fifty", "sixty","seventy", "eighty", "ninety"};
String teens[] = {"", "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen","seventeen", "eighteen", "nineteen"};
String thousands[] = {"", "thousand", "million", "billion", "trillion"};
int count = 0;
Stack<Integer> stack = new Stack<>();
int tempVal = value;
while (tempVal/1000 > 0) {
stack.push(tempVal % 1000);
count ++;
tempVal /= 1000;
}
do {
if (!total_number.isEmpty()) {
total_number+= " and ";
}
boolean added = false;
if (tempVal /100 > 0) {
total_number += number[tempVal/100]+" hundred ";
added = true;
}
tempVal %= 100;
if (tempVal > 0) {
if (added)
total_number += "and ";
if (tempVal < 11) {
total_number+= number[tempVal];
} else if (tempVal %10 == 0) {
total_number+= tens[tempVal/10];
} else if (tempVal/10 == 1) {
total_number += teens[tempVal %10];
} else {
total_number += tens[tempVal/10] + " "+ number[tempVal%10];
}
}
if (count > 0) {
if (tempVal > 0)
total_number += " " + thousands[count];
count --;
if (!stack.isEmpty())
tempVal = stack.pop();
else
tempVal = -1;
} else
tempVal = -1;
} while(tempVal != -1);
return total_number;
}
Here is the simple implementation using recursion:
private static String convertIntoWordsUsingRecursion(long number)
{
if (number == 0)
return "zero";
if (number < 0)
return "minus " + convertIntoWordsUsingRecursion(Math.abs(number));
String words = "";
if ((number / 10000000) > 0)
{
words += convertIntoWordsUsingRecursion(number / 10000000) + " crores ";
number %= 10000000;
}
if ((number / 100000) > 0)
{
words += convertIntoWordsUsingRecursion(number / 100000) + " lacs ";
number %= 100000;
}
if ((number / 1000) > 0)
{
words += convertIntoWordsUsingRecursion(number / 1000) + " thousand ";
number %= 1000;
}
if ((number / 100) > 0)
{
words += convertIntoWordsUsingRecursion(number / 100) + " hundred ";
number %= 100;
}
if (number > 0)
{
String[] unitsMap = new String[] { "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen" };
String[] tensMap = new String[] { "zero", "ten", "twenty", "thirty", "forty", "fifty", "sixty", "seventy", "eighty", "ninety" };
if (number < 20)
words += unitsMap[(int)number];
else
{
words += tensMap[(int)number / 10];
if ((number % 10) > 0)
words += " " + unitsMap[(int)number % 10];
}
}
return words;
}
private static String convertIntoWordsUsingRecursion(long number)
{
if (number == 0)
return "zero";
if (number < 0)
return "minus " + convertIntoWordsUsingRecursion(Math.abs(number));
String words = "";
if ((number / 10000000) > 0)
{
words += convertIntoWordsUsingRecursion(number / 10000000) + " crores ";
number %= 10000000;
}
if ((number / 100000) > 0)
{
words += convertIntoWordsUsingRecursion(number / 100000) + " lacs ";
number %= 100000;
}
if ((number / 1000) > 0)
{
words += convertIntoWordsUsingRecursion(number / 1000) + " thousand ";
number %= 1000;
}
if ((number / 100) > 0)
{
words += convertIntoWordsUsingRecursion(number / 100) + " hundred ";
number %= 100;
}
if (number > 0)
{
String[] unitsMap = new String[] { "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen" };
String[] tensMap = new String[] { "zero", "ten", "twenty", "thirty", "forty", "fifty", "sixty", "seventy", "eighty", "ninety" };
if (number < 20)
words += unitsMap[(int)number];
else
{
words += tensMap[(int)number / 10];
if ((number % 10) > 0)
words += " " + unitsMap[(int)number % 10];
}
}
return words;
}
private static String convertIntoWordsUsingRecursion(long number)
{
if (number == 0)
return "zero";
if (number < 0)
return "minus " + convertIntoWordsUsingRecursion(Math.abs(number));
String words = "";
if ((number / 10000000) > 0)
{
words += convertIntoWordsUsingRecursion(number / 10000000) + " crores ";
number %= 10000000;
}
if ((number / 100000) > 0)
{
words += convertIntoWordsUsingRecursion(number / 100000) + " lacs ";
number %= 100000;
}
if ((number / 1000) > 0)
{
words += convertIntoWordsUsingRecursion(number / 1000) + " thousand ";
number %= 1000;
}
if ((number / 100) > 0)
{
words += convertIntoWordsUsingRecursion(number / 100) + " hundred ";
number %= 100;
}
if (number > 0)
{
String[] unitsMap = new String[] { "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen" };
String[] tensMap = new String[] { "zero", "ten", "twenty", "thirty", "forty", "fifty", "sixty", "seventy", "eighty", "ninety" };
if (number < 20)
words += unitsMap[(int)number];
else
{
words += tensMap[(int)number / 10];
if ((number % 10) > 0)
words += " " + unitsMap[(int)number % 10];
}
}
return words;
}
private static String convertIntoWordsUsingRecursion(long number)
{
if (number == 0)
return "zero";
if (number < 0)
return "minus " + convertIntoWordsUsingRecursion(Math.abs(number));
String words = "";
if ((number / 10000000) > 0)
{
words += convertIntoWordsUsingRecursion(number / 10000000) + " crores ";
number %= 10000000;
}
if ((number / 100000) > 0)
{
words += convertIntoWordsUsingRecursion(number / 100000) + " lacs ";
number %= 100000;
}
if ((number / 1000) > 0)
{
words += convertIntoWordsUsingRecursion(number / 1000) + " thousand ";
number %= 1000;
}
if ((number / 100) > 0)
{
words += convertIntoWordsUsingRecursion(number / 100) + " hundred ";
number %= 100;
}
if (number > 0)
{
String[] unitsMap = new String[] { "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen" };
String[] tensMap = new String[] { "zero", "ten", "twenty", "thirty", "forty", "fifty", "sixty", "seventy", "eighty", "ninety" };
if (number < 20)
words += unitsMap[(int)number];
else
{
words += tensMap[(int)number / 10];
if ((number % 10) > 0)
words += " " + unitsMap[(int)number % 10];
}
}
return words;
}
Here is the Most simplest, very easy to extend up to any numbers (trillion...or any thing u wish).
This take advantage, how we read the number from left to right, here i just port how we read the number in code;
package Java;
import java.text.DecimalFormat;
/**
* Author: Nitin Gupta(nitin.gupta@walmart.com)
* Date: 15/03/19
* Description:
*/
public class ConvertNumberToWords {
private static final String[] tensNames = {
"",
" ten",
" twenty",
" thirty",
" forty",
" fifty",
" sixty",
" seventy",
" eighty",
" ninety"
};
private static final String[] numNames = {
"",
" one",
" two",
" three",
" four",
" five",
" six",
" seven",
" eight",
" nine",
" ten",
" eleven",
" twelve",
" thirteen",
" fourteen",
" fifteen",
" sixteen",
" seventeen",
" eighteen",
" nineteen"
};
private static String convertLessThanOneThousand(int number) {
String soFar;
if (number % 100 < 20) {
soFar = numNames[number % 100];
number /= 100;
} else {
soFar = numNames[number % 10];
number /= 10;
soFar = tensNames[number % 10] + soFar;
number /= 10;
}
if (number == 0) return soFar;
return numNames[number] + " hundred" + soFar;
}
private static String convertLessThanOneThousandWithAnd(int number) {
String soFar;
if (number % 100 < 20) {
soFar = numNames[number % 100];
number /= 100;
} else {
soFar = numNames[number % 10];
number /= 10;
soFar = tensNames[number % 10] + soFar;
number /= 10;
}
if (number == 0) return soFar;
if (!soFar.isEmpty())
return numNames[number] + " hundred and " + soFar;
return numNames[number] + " hundred" + soFar;
}
public static String convert(long number, boolean withoutAnd) {
// 0 to 999 999 999 999
if (number == 0) {
return "zero";
}
// pad with "0"
String mask = "000000000000";
DecimalFormat df = new DecimalFormat(mask);
String snumber = df.format(number);
// XXXnnnnnnnnn
int billions = Integer.parseInt(snumber.substring(0, 3));
// nnnXXXnnnnnn
int millions = Integer.parseInt(snumber.substring(3, 6));
// nnnnnnXXXnnn
int hundredThousands = Integer.parseInt(snumber.substring(6, 9));
// nnnnnnnnnXXX
int thousands = Integer.parseInt(snumber.substring(9, 12));
String tradBillions;
switch (billions) {
case 0:
tradBillions = "";
break;
default:
tradBillions = convertLessThanOneThousand(billions)
+ " billion ";
}
String result = tradBillions;
String tradMillions;
switch (millions) {
case 0:
tradMillions = "";
break;
default:
tradMillions = convertLessThanOneThousand(millions)
+ " million ";
}
result = result + tradMillions;
String tradHundredThousands;
switch (hundredThousands) {
case 0:
tradHundredThousands = "";
break;
case 1:
tradHundredThousands = "one thousand ";
break;
default:
tradHundredThousands = convertLessThanOneThousand(hundredThousands)
+ " thousand ";
}
result = result + tradHundredThousands;
String tradThousand;
if (!withoutAnd)
tradThousand = convertLessThanOneThousandWithAnd(thousands);
else
tradThousand = convertLessThanOneThousand(thousands);
result = result + tradThousand;
// remove extra spaces!
return result.replaceAll("^\\s+", "").replaceAll("\\b\\s{2,}\\b", " ");
}
static String convert(float number) {
String temp = String.valueOf(number);
String v[] = temp.split("\\.");
String left = convert(Long.parseLong(v[0]), true);
String right = convert(Long.parseLong(v[1]), true);
return left + " and " + right;
}
/**
* testing
*
* @param args
*/
public static void main(String[] args) {
System.out.println("*** " + convert(334.32f ));
// System.out.println("*** " + convert(0, true));
// System.out.println("*** " + convert(1, true));
// System.out.println("*** " + convert(16, true));
// System.out.println("*** " + convert(100, true));
// System.out.println("*** " + convert(118, true));
// System.out.println("*** " + convert(200, true));
// System.out.println("*** " + convert(219, true));
// System.out.println("*** " + convert(800, true));
// System.out.println("*** " + convert(801, true));
// System.out.println("*** " + convert(1316, true));
// System.out.println("*** " + convert(1000000, true));
// System.out.println("*** " + convert(2000000, true));
// System.out.println("*** " + convert(3000200, true));
// System.out.println("*** " + convert(700000, true));
// System.out.println("*** " + convert(9000000, true));
// System.out.println("*** " + convert(9001000, true));
// System.out.println("*** " + convert(123456789, true));
// System.out.println("*** " + convert(2147483647, true));
// System.out.println("*** " + convert(3000000010L, true));
/*
*** zero
*** one
*** sixteen
*** one hundred
*** one hundred eighteen
*** two hundred
*** two hundred nineteen
*** eight hundred
*** eight hundred one
*** one thousand three hundred sixteen
*** one million
*** two millions
*** three millions two hundred
*** seven hundred thousand
*** nine millions
*** nine millions one thousand
*** one hundred twenty three millions four hundred
** fifty six thousand seven hundred eighty nine
*** two billion one hundred forty seven millions
** four hundred eighty three thousand six hundred forty seven
*** three billion ten
**/
}
}
The number of combinations that can arise due to the size of the numbers are huge. So I think its a good idea to talk to the interviewer to see how large the number will be.
In the below example, I have taken a number till thousand. (Logic will remain the same for the larger numbers as well)
There are couple of special handling scenarios that we need to handle.
1. Number that ends in 0.
--> for such numbers, we dont call out last 0. example for 510, we convert this number to "five hundred ten". We dont say "five hundred ten zero"
2. Number that has 1 in its tenth position.
--> For such numbers we write **teen. Example for 513, we convert this number to "five hundred thirteen". We dont say "five hundred ten three"
3. Single digit numbers
Here is the code that handles
- Saurabh August 20, 2018