Search code examples
pythonordinal

Python Ordinal Number Script


We have an assignment that I'm stumped on. We have to write a function called int2ordinal that solves the following tasks:

Any number that ends in 11, 12 or 13 uses a th suffix

All remaining numbers that end in 1 use an st suffix

All remaining numbers that end in 2 use an nd suffix

All remaining numbers that end in 3 use an rd suffix

All remaining numbers use a th suffix

So basically write a function named int2ordinal that takes an integer as its only parameter and returns the number with its appropriate suffix as its result (stored in a string). For example, if the function is passed the integer 1 then it should return the string "1st". If it is passed the integer 12 then it should return the string "12th". If it is passed 2003 then it should return the string "2003rd".

We're using the remainder operator to extract the last digit of an integer by computing the remainder when the integer is divided by 10, and we're doing the same to extract the last two digits of an integer divided by 100. For example 29 % 10 is 9 while 1911 %100 is 11. We can then construct the string that needs to be returned by the function by converting the integer parameter into a string and concatenating the appropriate suffix using the + operator.

This is the code we have so far, we think the first half is totally incorrect:

def int2ordinal(day, month, year):

    if day % 10 == 1: return (str(day + "st"))
    if day % 10 == 2: return (str(day + "nd"))
    if day % 10 == 3: return (str(day + "rd"))
    if month % 10 == 1: return (str(month + "st"))
    if month % 10 == 2: return (str(month + "nd"))
    if month % 10 == 3: return (str(month + "rd"))
    if year % 100 == 1: return (str(year + "st"))
    if year % 100 == 2: return (str(year + "nd"))
    if year % 100 == 3: return (str(year + "rd")) 
    for i in range (11, 13): return (str(day + "th"))
    for i in range (11, 13): return (str(month + "th"))
    for i in range (11, 13): return (str(year + "th"))
    else: return (str(day + "th", month + "th", year + "th"))

def main():

  day = int(input("Enter a day between 1 and 31: "))
  month = int(input("Enter a month between 1 and 12: "))
  year = int(input("Enter a year between 1 and 2100: "))

  print("On the", int2ordinal(day), "day of the", int2ordinal(month), \
        "month of the", int2ordinal(year), "year, something amazing happened!")

main()

Any help would be amazing!


Solution

  • Why not keep it simple? Although untested, this should work.

    def int2ordinal(num):
        def formatted_num(suffix):   # Nested function.
            return str(num) + suffix
    
        end_digits = int(num[-2:])   # Gets last 2 chars of the string. Instead of repeating this operation on every if clause, better do it here.
        # You only really need to check if it either finishes with 1,2,3 - remaining values will have a th suffix.
        if end_digits in [1]:
            return formatted_num('st')
        elif end_digits in [2]:
            return formatted_num('nd')
        elif end_digits in [3]:
            return formatted_num('rd')
        else:
            return formatted_num('th')
    
    def main():
    
      day = input("Enter a day between 1 and 31: ")
      month = input("Enter a month between 1 and 12: ")
      year = input("Enter a year between 1 and 2100: ")
    
      print("On the", int2ordinal(day), "day of the", int2ordinal(month), \
            "month of the", int2ordinal(year), "year, something amazing happened!")
    
    main()
    

    Based on your answer in the comments then do this:

    def int2ordinal(num):
        num = str(num)
        if len(num) > 2:  # Will be a year, not necessarily consisting of four digits. Could be 333
            end_digits = int(num) % 100
        else:   # Will be month / day
            end_digits = int(num) % 10
        if end_digits == 1: return (num + "st")
        if end_digits == 2: return (num + "nd")
        if end_digits == 3: return (num + "rd")
        else: return (num + "th")
    
    
    def main():
    
      day = input("Enter a day between 1 and 31: ")
      month = input("Enter a month between 1 and 12: ")
      year = input("Enter a year between 1 and 2100: ")
    
      print("On the", int2ordinal(day), "day of the", int2ordinal(month), \
            "month of the", int2ordinal(year), "year, something amazing happened!")
    
    main()
    

    In general, try to avoid repeating code as much as you can. If you look at your original code, you're running num % 10/100 on every clause and also casting to str on every single return (no performance loss here, but repeating logic). Better avoid repeating such calls as much as possible, even if this code is not resource intensive, as you say you are an amateur: The earlier you learn this, the better.

    Also, a reason your original code would always have failed is that it had three arguments, you were always passing a day to it. Named arguments work like this:

    def foo(a,b,c):
        pass
    
    foo(a=0)
    foo(b=1)
    foo(c=2)
    

    Doing: foo(3)

    Results in foo() getting argument a, b and c will be None.