Convert integer to English words I was recently asked an interview question with regards to algorithm design. The challenge is as follows:

Given a 6 or less digits positive integer (0 - 999999 inclusive), write a function englishify(number: int) that returns the full English equivalent of that number. Here are some samples of the structure you are expected to generate:
1 - One
222 - Two Hundred And Twenty two
1234 - One Thousand, Two Hundred and Thirty Four
31337 - Thirty One Thousand, Three Hundred And Thirty Seven
100100 - One Hundred Thousand And One Hundred
200111 - Two Hundred Thousand, One Hundred And Eleven

As you may be able to see, there is a key requirement when it comes to formatting this:


There should be a comma, not 'And', after the thousands and before the hundreds, if both exist.


I have attempted this challenge with the code below:
def englishify(number):
    #Numbers 0-19 (unique numbers)
    OneToNine= 'One Two Three Four Five Six Seven Eight Nine'.split()
    TenToNineteen = 'Ten Eleven Twelve Thirteen Fourteen Fifteen Sixteen Seventeen Eighteen Nineteen'.split()
    ZeroToNineteen = [''] + OneToNine + TenToNineteen

    #Numbers &gt;= 20 at intervals of 10
    Tens = 'Twenty Thirty Forty Fifty Sixty Seventy Eighty Ninety'.split()

    #Additional function for ease of processing of numbers
    def englishifyHundreds(number):
    #Special case: Number = 0
        if number == 0:
            return 'Zero'

        #1. Number from 1-19
        if number &lt; 20:
            return ZeroToNineteen[number]

        #2. Number from 20-99
        if number &gt;= 20 and number &lt; 100:
            result = Tens[int(number/10)-2] + ' ' + ZeroToNineteen[int(number%10)]
            return result.rstrip()

        #3. Number from 100-999
        if number &gt;= 100:
            #Separating hundreds digit and tens digit
            tens = number - ((number//100)*100)

            #Accounting for edges = 0 (number = 100, 200, ...)
            if number%100 == 0:
                return ZeroToNineteen[int(number/100)] + ' Hundred'

            else:
                return ZeroToNineteen[int(number/100)] + ' Hundred And ' + englishifyHundreds(tens)

    #Actual processing of number
    if len(str(number)) &lt;= 3:
        return englishifyHundreds(number)

    else:
        #Splitting number into 'thousands' digits and 'hundreds' digits
        thousands = int(str(number)[:-3])
        hundreds = int(str(number)[-3:])

        #Accounting for edges = 0 (thousands = 1000, 2000, ...)
        if thousands % 1000 == 0:
            return englishifyHundreds(thousands) + ' Thousand'

        else:
            #Accounting for if hundreds == 0:
            if hundreds == 0:
                return englishifyHundreds(thousands) + ' Thousand'

            #Accounting for cases where comma is not necessary
            elif hundreds % 100 == 0 or hundreds &lt; 100:
                return englishifyHundreds(thousands) + ' Thousand And ' + englishifyHundreds(hundreds)

            #Remaining cases implementing comma
            else:
                return englishifyHundreds(thousands) + ' Thousand, ' + englishifyHundreds(hundreds)


I am currently trying to rack my brains thinking of ways to optimize this, but with my limited knowledge of recursions and algorithms this is the best I can churn out for now. Hopefully I can seek some opinions from some of the more experienced programmers around here.
It's often best to write this kind of function along with its tests.  Let's start with a simple test:
import doctest;

def englishify(number):
    &quot;&quot;&quot;Format NUMBER into standard English form.
    NUMBER must be in range [0..999999]
    &gt;&gt;&gt; englishify(0)
    'Zero'
    &quot;&quot;&quot;

    return 'Zero'

if __name__ == '__main__':
    doctest.testmod()

Now, start adding more tests and make each one pass before moving on to the next.
You'll find that when you reach the bigger numbers, there's a useful recursive property.  We can split off the thousands and the hundreds, format each non-zero part separately, and then join using one of the techniques from Joining words together with a comma, and “and”.  For example, consider these inputs:

123456 ⟶ 123 Thousand , 4 Hundred and 56
123056 ⟶ 123 Thousand and 56
123400 ⟶ 123 Thousand and 4 Hundred

Now those individual numbers can be formatted into words (and the last case will have two &quot;and&quot;s in normal English: &quot;One hundred and twenty-three thousand, four hundred and fifty-six.'

Modified code
import doctest;

def englishify(number):
    &quot;&quot;&quot;Format NUMBER into standard English form.
    NUMBER must be in range [0..999999]
    &gt;&gt;&gt; englishify(0)
    'Zero'
    &gt;&gt;&gt; englishify(10)
    'Ten'
    &gt;&gt;&gt; englishify(20)
    'Twenty'
    &gt;&gt;&gt; englishify(99)
    'Ninety Nine'
    &gt;&gt;&gt; englishify(100)
    'One Hundred'
    &gt;&gt;&gt; englishify(101)
    'One Hundred and One'
    &gt;&gt;&gt; englishify(1001)
    'One Thousand and One'
    &gt;&gt;&gt; englishify(1201)
    'One Thousand, Two Hundred and One'
    &gt;&gt;&gt; englishify(123201)
    'One Hundred and Twenty Three Thousand, Two Hundred and One'
    &quot;&quot;&quot;

    Units = [None, 'One', 'Two', 'Three', 'Four', 'Five',
             'Six', 'Seven', 'Eight', 'Nine',
             'Ten', 'Eleven', 'Twelve', 'Thirteen', 'Fourteen', 'Fifteen',
             'Sixteen', 'Seventeen', 'Eighteen', 'Nineteen']
    Tens = [None, None, 'Twenty', 'Thirty', 'Forty', 'Fifty',
            'Sixty', 'Seventy', 'Eighty', 'Ninety']

    if number &lt; 20:
        return Units[number] or 'Zero'

    if number &lt; 100:
        return ' '.join(filter(None, [Tens[number//10], Units[number%10]]))

    # Larger numbers - break down and englishify each part
    parts = list(filter(None,
                        map(lambda quantity, number:
                                englishify(number) + quantity if number else None,
                            [' Thousand', ' Hundred', ''],
                            [number // 1000, number // 100 % 10, number % 100])))

    if len(parts) == 1:
        return parts[0]
    return ' and '.join([', '.join(parts[:-1]), parts[-1]])


if __name__ == '__main__':
    doctest.testmod()

The extension to support millions and more should now be obvious - just add the unit and its extraction to the list passed to map().