# Exercise #6: Ordinal Suffix

ordinalSuffix(42)   '42nd' While cardinal numbers refer to the size of a group of objects like “four apples” or “1,000 tickets”, ordinal numbers refer to the place of an object in an ordered sequence like “first place” or “30th birthday”. This exercise involves numbers but is more an exercise in processing text than doing math.

Exercise Description

In English, ordinal numerals have suffixes such as the “th” in “30th” or “nd” in “2nd”. Write an `ordinalSuffix()` function with an integer parameter named `number` and returns a string of the number with its ordinal suffix. For example, ordinalSuffix(42) should return the string '42nd'.

You may use Python’s `str()` function to convert the integer argument to a string. Python’s `endswith()` string method could be useful for this exercise, but to maintain the challenge in this exercise, don’t use it as part of your solution.

These Python `assert` statements stop the program if their condition is `False`. Copy them to the bottom of your solution program. Your solution is correct if the following `assert` statements’ conditions are all True:

assert ordinalSuffix(0) == '0th'

assert ordinalSuffix(1) == '1st'

assert ordinalSuffix(2) == '2nd'

assert ordinalSuffix(3) == '3rd'

assert ordinalSuffix(4) == '4th'

assert ordinalSuffix(10) == '10th'

assert ordinalSuffix(11) == '11th'

assert ordinalSuffix(12) == '12th'

assert ordinalSuffix(13) == '13th'

assert ordinalSuffix(14) == '14th'

assert ordinalSuffix(101) == '101st'

Try to write a solution based on the information in this description. If you still have trouble solving this exercise, read the Solution Design and Special Cases and Gotchas sections for additional hints.

Prerequisite concepts: strings, `in` operator, slices, string concatenation

Solution Design

The ordinal suffix depends on the last two digits in the number:

·       If the last two digits end with 11, 12, or 13 then the suffix is “th.”

·       If the number ends with 1, the suffix is “st.”

·       If the number ends with 2, the suffix is “nd.”

·       If the number ends with 3, the suffix is “rd.”

·       Every other number has a suffix of “th.”

Our code becomes much easier to write if we call the str() function to convert the integer value in number to a string first. Then you can use negative indexes in Python to find the last digit in this string. You can store the string form in a variable named `numberStr`. Just as numberStr and `numberStr` evaluate to the first and second character in `numberStr`, `numberStr[-1]` and `numberStr[-2]` evaluate to the last and second to last character in `numberStr`. Therefore, you can use `numberStr[-1]` to check if the last digit is 1, 2, or 3.

To find the last two digits, you can use Python slices to get a substring from a string by specifying the start and end index of the slice. For example, `numberStr[0:3]` evaluates to the characters in `numberStr` from index `0` up to, but not including, index `3`. Enter the following in the interactive shell:

>>> numberStr = '41096'

>>> numberStr[0:3]

'410'

If `numberStr` were `'41096'`, `numberStr[0:3]` evaluates to `'410'`. If you leave out the first index, Python assumes you mean “the start of the string.” For example, `numberStr[:3]` means the same thing as `numberStr[0:3]`. If you leave out the second index, Python assumes you mean “the end of the string.” For example, numberStr[3:] means the same thing as `numberStr[3:len(numberStr)]` or `'96'`. Enter the following into the interactive shell:

>>> numberStr = '41096'

>>> numberStr[:3]

'410'

>>> numberStr[3:]

'96'

You can combine slices and negative indexes. For example, numberStr[-2:] means the slice starts from the second to last character in `numberStr` and continues to the end of the string. This is how `numberStr[-2:]` becomes the shorthand for “the last two characters in `numberStr`.” You can use this to determine if the number ends with 11, 12, or 13. Enter the following into the interactive shell:

>>> numberStr = '41096'

>>> numberStr[-2:]

'96'

>>> numberStr = '987654321'

>>> numberStr[-2:]

'21'

If you need to compare a variable to multiple values, you can use the in keyword and put the values in a tuple. For example, instead of the lengthy condition numberStr[-2:] == '11' or numberStr[-2:] == '12' or numberStr[-2:] == '13', you can have the equivalent and more concise numberStr[-2:] in ('11', '12', '13'). Enter the following into the interactive shell:

>>> numberStr = '41096'

>>> numberStr[-2:] in ('11', '12', '13')

False

>>> numberStr = '512'

>>> numberStr[-2:] in ('11', '12', '13')

True

You’ll use a similar expression in this exercise’s solution.

Special Cases and Gotchas

Ensure that the number ends with 11, 12, or 13 before checking if it ends with 1, 2, or 3. Otherwise, you may end up programming your function to return `'213rd'` instead of '213th'. Also, notice that `'0'` has an ordinal suffix of “th”: `'0th'`.

Now try to write a solution based on the information in the previous sections. If you still have trouble solving this exercise, read the Solution Template section for additional hints.

Solution Template

Try to first write a solution from scratch. But if you have difficulty, you can use the following partial program as a starting place. Copy the following code from https://invpy.com/ordinalsuffix-template.py and paste it into your code editor. Replace the underscores with code to make a working program:

def ordinalSuffix(number):

numberStr = str(number)

# 11, 12, and 13 have the suffix th:

if numberStr[____:] in ('11', ____, ____):

return numberStr + 'th'

# Numbers that end with 1 have the suffix st:

if numberStr[____] == '1':

return numberStr + 'st'

# Numbers that end with 2 have the suffix nd:

if numberStr[____] == ____:

return numberStr + 'nd'

# Numbers that end with 3 have the suffix rd:

if numberStr[____] == ____:

return numberStr + 'rd'

# All other numbers end with th:

return ____ + ____

The complete solution for this exercise is given in Appendix A and https://invpy.com/ordinalsuffix.py. You can view each step of this program as it runs under a debugger at https://invpy.com/ordinalsuffix-debug/.

Another Solution Design

Instead of using the `str()` function to convert the number to a string and examining the digits at the end, you could leave it as an integer and determine the last digit with the % modulo operator.

Any number modulo 10 evaluates to the digit in the one’s place of the number. You can use modulo 100 to get the last two digits. For example, enter the following into the interactive shell:

`>>> 42 % 10`

`2`

`>>> 12345 % 10`

`5`

`>>> 12345 % 100`

`45`

Using this information, write an alternative solution for this exercise using modulo. If you need additional hints, replace the underscores in the following solution template with code:

def ordinalSuffix(number):

# 11, 12, and 13 have the suffix th:

if ____ % 100 in (11, ____, ____):

return str(number) + 'th'

# Numbers that end with 1 have the suffix st:

if ____ % 10 == ____:

return str(number) + 'st'

# Numbers that end with 2 have the suffix nd:

if ____ % 10 == ____:

return str(number) + 'nd'

# Numbers that end with 3 have the suffix rd:

if ____ % 10 == ____:

return str(number) + 'rd'

# All other numbers end with th:

return ____(____) + ____

The complete solution for this exercise is given in Appendix A and https://invpy.com/ordinalsuffix2.py. You can view each step of this program as it runs under a debugger at https://invpy.com/ordinalsuffix2-debug/.