2
\$\begingroup\$

I'm posting my code for a LeetCode problem copied here. If you would like to review, please do so. Thank you for your time!

Problem

Convert a non-negative integer to its English words representation. Given input is guaranteed to be less than 2^31 - 1.

Inputs

123
1234567891
151
1414312
1234
1241234113

Outputs

"One Hundred Twenty Three"
"One Billion Two Hundred Thirty Four Million Five Hundred Sixty Seven Thousand Eight Hundred Ninety One"
"One Hundred Fifty One"
"One Million Four Hundred Fourteen Thousand Three Hundred Twelve"
"One Thousand Two Hundred Thirty Four"
"One Billion Two Hundred Forty One Million Two Hundred Thirty Four Thousand One Hundred Thirteen"

Code

#include <string>

class Solution {
    std::string zero_to_twenty[20] = {"Zero", "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten", "Eleven", "Twelve", "Thirteen", "Fourteen", "Fifteen", "Sixteen", "Seventeen", "Eighteen", "Nineteen"};
    std::string tens_and_zero[10] = {"Zero", "Ten", "Twenty", "Thirty", "Forty", "Fifty", "Sixty", "Seventy", "Eighty", "Ninety"};
    std::string SPACE = " ";
    std::string BILLION = "Billion";
    std::string MILLION = "Million";
    std::string THOUSAND = "Thousand";
    std::string HUNDRED = "Hundred";
    std::string ZERO = "Zero";
    std::string EMPTY_STRING = "";
    static inline constexpr int one_billion = 1e9;
    static inline constexpr int one_million = 1e6;
    static inline constexpr int one_thousand = 1e3;
    static inline constexpr int one_hundred = 100;
    static inline constexpr int twenty = 20;
    static inline constexpr int ten = 10;

public:
    inline std::string numberToWords(int num) {
        if (num == 0) {
            return ZERO;

        } else {
            std::string words = int2string(num);
            return words.substr(1, words.length() - 1);
        }
    }

private:
    inline std::string int2string(const int n) {
        if (n >= one_billion) {
            return int2string(n / one_billion) + SPACE + BILLION + int2string(n % one_billion);

        } else if (n >= one_million) {
            return int2string(n / one_million) + SPACE + MILLION + int2string(n % one_million);

        } else if (n >= one_thousand) {
            return int2string(n / one_thousand) + SPACE + THOUSAND + int2string(n % one_thousand);

        } else if (n >= one_hundred) {
            return int2string(n / one_hundred) + SPACE + HUNDRED + int2string(n % one_hundred);

        } else if (n >= twenty) {
            return SPACE + tens_and_zero[n / ten] + int2string(n % ten);

        } else if (n >= 1) {
            return SPACE + zero_to_twenty[n];

        } else {
            return EMPTY_STRING;
        }
    }
};

References

\$\endgroup\$

2 Answers 2

2
\$\begingroup\$

Take a look at what translating

1241234113

results in when aligned slightly differently

                       One       Billion 
Two  Hundred   Forty   One       Million 
Two  Hundred   Thirty  Four      Thousand 
One  Hundred           Thirteen  

you can see that there are several patterns here.

  1. Every number can be chunked into groups of 3 digits like this 1,241,234,113.

  2. Each chunk has a different value for the last column, which is one of "Billion", "Million", etc.

  3. Within each chunk, there is one digit at the hundreds place.

  4. Within each chunk, the last 2 digits have a special case till 20, otherwise it's a special word for the ten's place, and the one's place.

So the only variables you need are just

std::string const till_twenty[20] = {"", "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten", "Eleven", "Twelve", "Thirteen", "Fourteen", "Fifteen", "Sixteen", "Seventeen", "Eighteen", "Nineteen"};
std::string const tens_place[10] = {"", "Ten", "Twenty", "Thirty", "Forty", "Fifty", "Sixty", "Seventy", "Eighty", "Ninety"};
std::string const thousands[4] = {"", "Thousand", "Million", "Billion"};

Note that I've renamed the variables slightly, and made them const. Also, there's no need for the word Zero, since that will only be written if the entire number is 0.

Now you can build up the functions for the 3 digit chunks

//for the first digit    
std::string hundreds_place(int n) {
   return n ? till_twenty[n] + " Hundred " : "";
}
  
// for the 2nd and 3rd digit  
std::string ones_and_tens_place(int n) {
    return n <= 20 ? till_twenty[n] : tens_place[n / 10] + 
                                      (n % 10 ? " " + till_twenty[n % 10] : "")
}

// putting all 3 digits together
std::string by_hundreds(int n) {
    return hundreds_place(n / 100) + ones_and_tens_place(n % 100);
}

Now you can recursively build the 3 digit numbers by keeping track of which power of 1000 is being currently processed

std::string by_thousands(int n, int i) {    // i keeps track of the chunk
    return n ? by_thousands(n / 1000, i + 1) + 
               by_hundreds(n % 1000) + " " 
               + thousands[i] + " "
             : "";
}

and then finally it can all be put together

std::string numberToWords(int num) {
    std::string res = num ? by_thousands(num, 0) : "Zero  ";
    // with a bit of processing to get rid of trailing spaces
    return res.substr(0, res.length() - 2);        
}
\$\endgroup\$
0
1
\$\begingroup\$
inline std::string int2string(const int n) {
    if (n >= one_billion) {
        return int2string(n / one_billion) + " "+ BILLION + int2string(n % one_billion);

    } else if (n >= one_million) {
        return int2string(n / one_million) + " " + MILLION + int2string(n % one_million);

    } else if (n >= one_thousand) {
        return int2string(n / one_thousand) + " " + THOUSAND + int2string(n % one_thousand);

    } else if (n >= 100) {
        return int2string(n / 100) + " " + HUNDRED + int2string(n % 100);

    } else if (n >= 20) {
        return " " + tens_and_zero[n / ten] + int2string(n % 10);

    } else if (n >= 1) {
        return " " + zero_to_twenty[n];

    } 
    return "";      
}

There isn't much wrong structurally, but i think the changes I made improves readability somewhat.

\$\endgroup\$
0

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.